Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions analytics/analytics_package/analytics/static_site/fetch.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
"""Fetch analytics data from GA4 for the static site."""

import re
from datetime import date
from urllib.parse import urlparse, parse_qs

from .. import sheets_elements as elements
from ..api import parse_filter_expressions
from .._sheets_utils import get_data_df_from_fields
from ..entities import (
DIMENSION_YEAR_MONTH,
Expand Down Expand Up @@ -337,6 +339,7 @@ def fetch_data(
exclude_pages=None,
base_dimension_filter=None,
search_path=None,
exclude_dates=None,
):
"""Fetch all analytics data for the static site.

Expand All @@ -350,13 +353,30 @@ def fetch_data(
exclude_pages: Optional list of page paths to exclude from pageview data.
base_dimension_filter: Optional GA4 dimension filter dict applied to all queries.
search_path: Optional search page path to extract search queries from (e.g., "/search").
exclude_dates: Optional list of dates (YYYY-MM-DD) to exclude from all queries,
e.g. days with known synthetic/bot traffic. Applies to GA4 queries only,
not to data merged from historic_data_path.

Returns:
Dict containing DataFrames and stats for each data type.
"""
if custom_events is None:
custom_events = []

if exclude_dates:
for d in exclude_dates:
if not re.fullmatch(r"\d{4}-\d{2}-\d{2}", d):
raise ValueError(f"exclude_dates entries must be YYYY-MM-DD, got: {d!r}")
date.fromisoformat(d)
base_dimension_filter = parse_filter_expressions(
[
base_dimension_filter,
";".join(f"date!={d.replace('-', '')}" for d in exclude_dates),
],
False,
)
print(f"Excluding dates from all queries: {', '.join(exclude_dates)}")

report_dates = elements.get_bounds_for_month_and_prev(current_month)
start_date_current = report_dates["start_current"]
end_date_current = report_dates["end_current"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def generate_site(
exclude_pages=None,
base_dimension_filter=None,
search_path=None,
exclude_dates=None,
):
"""Generate a static analytics site.

Expand All @@ -48,6 +49,9 @@ def generate_site(
base_dimension_filter: Optional GA4 dimension filter dict applied to all queries
(e.g., an audience filter to exclude bot/tutorial traffic).
search_path: Optional search page path to extract search queries from (e.g., "/search").
exclude_dates: Optional list of dates (YYYY-MM-DD) to exclude from all queries,
e.g. days with known synthetic/bot traffic. Applies to GA4 queries only,
not to data merged from historic_data_path.
"""
if custom_events is None:
custom_events = []
Expand All @@ -69,6 +73,7 @@ def generate_site(
exclude_pages=exclude_pages,
base_dimension_filter=base_dimension_filter,
search_path=search_path,
exclude_dates=exclude_dates,
)

if title_resolver:
Expand Down
3 changes: 3 additions & 0 deletions analytics/anvil-explorer-sheets/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
# The name of the spreadsheet with the report
SHEET_NAME = "AnVIL Explorer"
ANVIL_EXPLORER_ID = "383267328"
# Dates of known synthetic/bot traffic (headless-browser burst, likely a load test)
# to exclude from reports; see DataBiosphere/data-browser#4907.
EXCLUDE_BOT_TRAFFIC_DATES = ["2025-02-10", "2025-02-11"]
SECRET_NAME = 'ANVIL_ANALYTICS_REPORTING_CLIENT_SECRET_PATH'
GA_PROPERTY_PORTAL = "368678391" # AnVIL Explorer - GA4
ANALYTICS_START = "2024-01-01"
Expand Down
3 changes: 2 additions & 1 deletion analytics/anvil-explorer-sheets/generate_static_site.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import analytics.api as ga
from analytics.static_site import generate_site, enrich_detail_records, make_event_charts
from constants import CURRENT_MONTH, ANVIL_EXPLORER_ID, SECRET_NAME, ANALYTICS_START, OAUTH_PORT
from constants import CURRENT_MONTH, ANVIL_EXPLORER_ID, SECRET_NAME, ANALYTICS_START, OAUTH_PORT, EXCLUDE_BOT_TRAFFIC_DATES
from utils import fetch_dataset_title_map

os.environ.setdefault(SECRET_NAME, "../../.credentials/anvil_ga4_credentials.json")
Expand Down Expand Up @@ -95,4 +95,5 @@ def resolve_dataset_titles(data):
event_charts=make_event_charts("Dataset", "/datasets", "2026-03-01"),
title_resolver=resolve_dataset_titles,
access_request_urls=["duos.org", "dbgap.ncbi.nlm.nih.gov"],
exclude_dates=EXCLUDE_BOT_TRAFFIC_DATES,
)
2 changes: 1 addition & 1 deletion gh-pages/anvil-explorer/data/meta.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"generated_at": "2026-08-06 22:50:04",
"generated_at": "2026-08-07 01:01:11",
"current_month": "2026-07",
"current_month_start": "2026-07-01",
"current_month_end": "2026-07-31",
Expand Down
4 changes: 2 additions & 2 deletions gh-pages/anvil-explorer/data/monthly_traffic.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@
},
{
"month": "2025-02",
"users": 9480,
"pageviews": 19951
"users": 277,
"pageviews": 2239
},
{
"month": "2025-01",
Expand Down
Loading