Skip to content

Commit ea1cec1

Browse files
chore: update analytics to May 2026 #4857
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 4d15705 commit ea1cec1

51 files changed

Lines changed: 15613 additions & 14150 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

analytics/analytics_package/analytics/static_site/charts.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,21 @@ def make_event_charts(entity_label, entity_path, chart_start):
2020
"title": "Export to Terra",
2121
"series": [
2222
{"label": f"Single {entity_label}", "event_key": "dataset_analyze_in_terra_requested", "event_name": "dataset_analyze_in_terra_requested"},
23-
{"label": "Cross-Dataset", "event_key": "index_analyze_in_terra_requested", "event_name": "index_analyze_in_terra_requested"},
23+
{"label": f"Cross-{entity_label}", "event_key": "index_analyze_in_terra_requested", "event_name": "index_analyze_in_terra_requested"},
2424
],
2525
},
2626
{
2727
"title": "curl Command",
2828
"series": [
2929
{"label": f"Single {entity_label}", "event_key": "dataset_bulk_download_requested", "event_name": "bulk_download_requested", "page_path_regex": rf"^/{path_segment}/[0-9a-f-]+"},
30-
{"label": "Cross-Dataset", "event_key": "index_bulk_download_requested", "event_name": "bulk_download_requested", "page_path_regex": rf"^(?!/{path_segment}/[0-9a-f-]+)"},
30+
{"label": f"Cross-{entity_label}", "event_key": "index_bulk_download_requested", "event_name": "bulk_download_requested", "page_path_regex": rf"^(?!/{path_segment}/[0-9a-f-]+)"},
3131
],
3232
},
3333
{
3434
"title": "File Manifest",
3535
"series": [
3636
{"label": f"Single {entity_label}", "event_key": "dataset_file_manifest_requested", "event_name": "dataset_file_manifest_requested"},
37-
{"label": "Cross-Dataset", "event_key": "index_file_manifest_requested", "event_name": "index_file_manifest_requested"},
37+
{"label": f"Cross-{entity_label}", "event_key": "index_file_manifest_requested", "event_name": "index_file_manifest_requested"},
3838
],
3939
},
4040
],

analytics/analytics_package/analytics/static_site/export.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,14 @@ def export_data(data, config, current_month, analytics_start, custom_events, out
148148
for event in custom_events:
149149
key = event_key(event)
150150
stats = data.get(f"event_{key}", {"current": 0, "prior": 0, "change": None})
151-
events_output.append({
151+
event_entry = {
152152
"event_name": key,
153153
"label": event["label"],
154154
**stats,
155-
})
155+
}
156+
if event.get("detail_file_column"):
157+
event_entry["detail_file_column"] = event["detail_file_column"]
158+
events_output.append(event_entry)
156159

157160
with open(os.path.join(output_dir, "custom_events.json"), "w") as f:
158161
json.dump(events_output, f, indent=2)
@@ -211,7 +214,6 @@ def export_data(data, config, current_month, analytics_start, custom_events, out
211214
"prior_month_end": dates.get("end_prior", ""),
212215
"analytics_start": analytics_start,
213216
"sessions": data.get("sessions", {}),
214-
"engaged_sessions": data.get("engaged_sessions", {}),
215217
"engagement_rate": data.get("engagement_rate", {}),
216218
}
217219

analytics/analytics_package/analytics/static_site/fetch.py

Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,6 @@
2222
"alias": "Engagement Rate",
2323
}
2424

25-
METRIC_ENGAGED_SESSIONS = {
26-
"id": "engagedSessions",
27-
"alias": "Engaged Sessions",
28-
}
29-
3025
# Regex matching page paths that are clearly not real pages (bot probes,
3126
# broken markdown links, asset requests, etc.).
3227
SUSPICIOUS_PAGE_PATH_RE = re.compile(
@@ -49,11 +44,13 @@ def event_key(event):
4944
return event.get("key", event["event_name"])
5045

5146

52-
def _count_events(event_name, params, page_path_regex=None):
53-
"""Fetch event count, optionally filtered by page path regex."""
47+
def _count_events(event_name, params, page_path_regex=None, click_url_regex=None):
48+
"""Fetch event count, optionally filtered by page path and/or click URL regex."""
5449
dimensions = [DIMENSION_EVENT_NAME]
5550
if page_path_regex:
5651
dimensions.append(DIMENSION_PAGE_PATH)
52+
if click_url_regex:
53+
dimensions.append(DIMENSION_CUSTOM_URL)
5754

5855
df = get_data_df_from_fields(
5956
[METRIC_EVENT_COUNT],
@@ -66,27 +63,29 @@ def _count_events(event_name, params, page_path_regex=None):
6663
return 0
6764

6865
if page_path_regex:
69-
pattern = re.compile(page_path_regex)
70-
mask = df[DIMENSION_PAGE_PATH["alias"]].str.match(pattern, na=False)
71-
return int(df.loc[mask, METRIC_EVENT_COUNT["alias"]].sum())
66+
df = df[df[DIMENSION_PAGE_PATH["alias"]].str.match(page_path_regex, na=False)]
67+
68+
if click_url_regex:
69+
df = df[df[DIMENSION_CUSTOM_URL["alias"]].str.contains(click_url_regex, na=False)]
7270

7371
return int(df[METRIC_EVENT_COUNT["alias"]].sum())
7472

7573

76-
def get_custom_event_change(event_name, params_current, params_prior, page_path_regex=None):
74+
def get_custom_event_change(event_name, params_current, params_prior, page_path_regex=None, click_url_regex=None):
7775
"""Fetch a custom event count with month-over-month change.
7876
7977
Args:
8078
event_name: GA4 event name (e.g., "chat_submitted").
8179
params_current: Analytics params for the current period.
8280
params_prior: Analytics params for the prior period.
8381
page_path_regex: Optional regex to filter by page path.
82+
click_url_regex: Optional regex to filter by click URL.
8483
8584
Returns:
8685
Dict with "current", "prior", and "change" keys.
8786
"""
88-
current_count = _count_events(event_name, params_current, page_path_regex)
89-
prior_count = _count_events(event_name, params_prior, page_path_regex)
87+
current_count = _count_events(event_name, params_current, page_path_regex, click_url_regex)
88+
prior_count = _count_events(event_name, params_prior, page_path_regex, click_url_regex)
9089

9190
change = None
9291
if prior_count > 0:
@@ -95,21 +94,26 @@ def get_custom_event_change(event_name, params_current, params_prior, page_path_
9594
return {"current": current_count, "prior": prior_count, "change": change}
9695

9796

98-
def get_event_detail_table(event_name, params, page_path_regex=None):
97+
def get_event_detail_table(event_name, params, page_path_regex=None, click_url_regex=None):
9998
"""Fetch event details broken down by page path and entity name.
10099
101100
Args:
102101
event_name: GA4 event name.
103102
params: Analytics params for the period.
104103
page_path_regex: Optional regex to filter by page path.
104+
click_url_regex: Optional regex to filter by click URL.
105105
106106
Returns:
107107
List of dicts with "page_path", "entity_name", and "count" keys,
108-
sorted by count descending.
108+
sorted by count descending. Includes "click_url" when click_url_regex is used.
109109
"""
110+
dimensions = [DIMENSION_EVENT_NAME, DIMENSION_PAGE_PATH, DIMENSION_ENTITY_NAME]
111+
if click_url_regex:
112+
dimensions.append(DIMENSION_CUSTOM_URL)
113+
110114
df = get_data_df_from_fields(
111115
[METRIC_EVENT_COUNT],
112-
[DIMENSION_EVENT_NAME, DIMENSION_PAGE_PATH, DIMENSION_ENTITY_NAME],
116+
dimensions,
113117
dimension_filter=f"eventName=={event_name}",
114118
**params,
115119
)
@@ -118,14 +122,25 @@ def get_event_detail_table(event_name, params, page_path_regex=None):
118122
return []
119123

120124
if page_path_regex:
121-
pattern = re.compile(page_path_regex)
122-
df = df[df[DIMENSION_PAGE_PATH["alias"]].str.match(pattern, na=False)]
125+
df = df[df[DIMENSION_PAGE_PATH["alias"]].str.match(page_path_regex, na=False)]
126+
127+
if click_url_regex:
128+
df = df[df[DIMENSION_CUSTOM_URL["alias"]].str.contains(click_url_regex, na=False)]
123129

124130
if len(df) == 0:
125131
return []
126132

127-
result = df[[DIMENSION_PAGE_PATH["alias"], DIMENSION_ENTITY_NAME["alias"], METRIC_EVENT_COUNT["alias"]]].copy()
128-
result.columns = ["page_path", "entity_name", "count"]
133+
export_cols = [DIMENSION_PAGE_PATH["alias"], DIMENSION_ENTITY_NAME["alias"]]
134+
output_names = ["page_path", "entity_name"]
135+
if click_url_regex:
136+
export_cols.append(DIMENSION_CUSTOM_URL["alias"])
137+
output_names.append("click_url")
138+
export_cols.append(METRIC_EVENT_COUNT["alias"])
139+
output_names.append("count")
140+
141+
result = df[export_cols].copy()
142+
result.columns = output_names
143+
result["count"] = result["count"].astype(int)
129144
result = result.sort_values("count", ascending=False)
130145
return result.to_dict(orient="records")
131146

@@ -396,15 +411,13 @@ def fetch_data(
396411

397412
print("Fetching sessions and engagement data...")
398413
df_sessions_current = get_data_df_from_fields(
399-
[METRIC_SESSIONS, METRIC_ENGAGED_SESSIONS, METRIC_ENGAGEMENT_RATE], [], **params,
414+
[METRIC_SESSIONS, METRIC_ENGAGEMENT_RATE], [], **params,
400415
)
401416
df_sessions_prior = get_data_df_from_fields(
402-
[METRIC_SESSIONS, METRIC_ENGAGED_SESSIONS, METRIC_ENGAGEMENT_RATE], [], **params_prior,
417+
[METRIC_SESSIONS, METRIC_ENGAGEMENT_RATE], [], **params_prior,
403418
)
404419
sessions_current = int(df_sessions_current[METRIC_SESSIONS["alias"]].sum()) if len(df_sessions_current) > 0 else 0
405420
sessions_prior = int(df_sessions_prior[METRIC_SESSIONS["alias"]].sum()) if len(df_sessions_prior) > 0 else 0
406-
engaged_sessions_current = int(df_sessions_current[METRIC_ENGAGED_SESSIONS["alias"]].sum()) if len(df_sessions_current) > 0 else 0
407-
engaged_sessions_prior = int(df_sessions_prior[METRIC_ENGAGED_SESSIONS["alias"]].sum()) if len(df_sessions_prior) > 0 else 0
408421
engagement_current = float(df_sessions_current[METRIC_ENGAGEMENT_RATE["alias"]].mean()) if len(df_sessions_current) > 0 else 0
409422
engagement_prior = float(df_sessions_prior[METRIC_ENGAGEMENT_RATE["alias"]].mean()) if len(df_sessions_prior) > 0 else 0
410423

@@ -440,10 +453,6 @@ def fetch_data(
440453
"current": sessions_current,
441454
"prior": sessions_prior,
442455
},
443-
"engaged_sessions": {
444-
"current": engaged_sessions_current,
445-
"prior": engaged_sessions_prior,
446-
},
447456
"engagement_rate": {
448457
"current": engagement_current,
449458
"prior": engagement_prior,
@@ -470,12 +479,14 @@ def fetch_data(
470479
data[f"event_{key}"] = get_custom_event_change(
471480
event["event_name"], params, params_prior,
472481
page_path_regex=event.get("page_path_regex"),
482+
click_url_regex=event.get("click_url_regex"),
473483
)
474484
if event.get("detail_table"):
475485
print(f"Fetching {event['label']} detail table...")
476486
data[f"event_{key}_detail"] = get_event_detail_table(
477487
event["event_name"], params,
478488
page_path_regex=event.get("page_path_regex"),
489+
click_url_regex=event.get("click_url_regex"),
479490
)
480491

481492
if event_charts:

analytics/analytics_package/analytics/static_site/template/index.html

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -489,11 +489,10 @@ <h3 class="fui-card-header-title fui-heading-xsmall">Filter Selections</h3>
489489
const previous = traffic[1] || {};
490490

491491
const sessions = meta.sessions || {};
492-
const engagedSessions = meta.engaged_sessions || {};
493492
const engagement = meta.engagement_rate || {};
494493

495494
const usersChange = pctChange(latest.users, previous.users);
496-
const engagedSessionsChange = pctChange(engagedSessions.current, engagedSessions.prior);
495+
const sessionsChange = pctChange(sessions.current, sessions.prior);
497496
const pageviewsChange = pctChange(latest.pageviews, previous.pageviews);
498497
const engagementChange = pctChange(engagement.current, engagement.prior);
499498

@@ -511,9 +510,9 @@ <h3 class="fui-card-header-title fui-heading-xsmall">Filter Selections</h3>
511510
`Total number of unique individuals who visited your site during ${monthName}.`
512511
) +
513512
statCard(
514-
formatNumber(engagedSessions.current != null ? engagedSessions.current : (sessions.current || 0)), 'Engaged Sessions',
515-
engagedSessionsChange,
516-
`Sessions where users actively engaged with your site during ${monthName} (stayed 10+ seconds, viewed 2+ pages, or triggered a conversion). <a href="https://support.google.com/analytics/answer/11109416" target="_blank" rel="noopener noreferrer">Learn more</a>.`
513+
formatNumber(sessions.current || 0), 'User Sessions',
514+
sessionsChange,
515+
`Total number of visits to your site during ${monthName}. A single user can have multiple sessions.`
517516
) +
518517
statCard(
519518
formatNumber(latest.pageviews), 'Pageviews',
@@ -580,7 +579,8 @@ <h3 class="fui-card-header-title fui-heading-xsmall">Filter Selections</h3>
580579
if (chartDataByKey[card.event_key] && chartDataByKey[card.event_key].length > 0) {
581580
const canvasId = `event-trend-chart-${chartIndex++}`;
582581
const parts = card.label.split('\n');
583-
const chartTitle = escapeHtml(rowLabel) + ' Over Time' + (parts[1] ? ` (${escapeHtml(parts[1].replace(/[()]/g, ''))})` : '');
582+
const cardLabel = parts[0];
583+
const chartTitle = escapeHtml(cardLabel) + ' Over Time' + (parts[1] ? ` (${escapeHtml(parts[1].replace(/[()]/g, ''))})` : '');
584584
html += `
585585
<div class="fui-card fui-grid-item-6">
586586
<div class="fui-card-header">
@@ -662,6 +662,7 @@ <h3 class="fui-card-header-title fui-heading-xsmall">${chartTitle}</h3>
662662
if (!detail) continue;
663663

664664
const hasDatasetTitle = detail.some(r => r.dataset_title);
665+
const hasClickUrl = detail.some(r => r.click_url);
665666
const isEmpty = detail.length === 0;
666667

667668
let tableContent;
@@ -672,9 +673,12 @@ <h3 class="fui-card-header-title fui-heading-xsmall">${chartTitle}</h3>
672673
const label = r.dataset_title || r.entity_name || r.page_path || '-';
673674
const link = r.page_path ? `${siteBase}${r.page_path.replace(/\/export.*/, '')}` : null;
674675
const cell = link ? `<a href="${safeHref(link)}" target="_blank" rel="noopener noreferrer">${escapeHtml(label)}</a>` : escapeHtml(label);
675-
return `<tr><td>${cell}</td><td class="col-number">${formatNumber(r.count)}</td></tr>`;
676+
const fileTd = hasClickUrl ? `<td class="truncate">${escapeHtml(r.file_label || fileNameFromUrl(r.click_url))}</td>` : '';
677+
return `<tr><td>${cell}</td>${fileTd}<td class="col-number">${formatNumber(r.count)}</td></tr>`;
676678
}).join('');
677-
tableContent = `<table class="detail-table collapsible-table"><thead><tr><th>${escapeHtml(entityLabel)}</th><th class="col-number">Count</th></tr></thead><tbody>${rows}</tbody></table>`;
679+
const fileColLabel = event.detail_file_column || 'File';
680+
const fileHeader = hasClickUrl ? `<th>${escapeHtml(fileColLabel)}</th>` : '';
681+
tableContent = `<table class="detail-table collapsible-table"><thead><tr><th>${escapeHtml(entityLabel)}</th>${fileHeader}<th class="col-number">Count</th></tr></thead><tbody>${rows}</tbody></table>`;
678682
} else {
679683
const rows = detail.map(r => {
680684
const raw = r.entity_name && r.entity_name !== '(not set)' ? r.entity_name : null;
@@ -945,6 +949,12 @@ <h3 class="fui-card-header-title fui-heading-xsmall">${escapeHtml(event.label)}
945949
}
946950
}
947951

952+
function fileNameFromUrl(url) {
953+
if (!url) return '-';
954+
const parts = url.split('/');
955+
return parts[parts.length - 1] || url;
956+
}
957+
948958
function formatChange(change) {
949959
if (change == null) return '-';
950960
return (change >= 0 ? '+' : '') + (change * 100).toFixed(1) + '%';

analytics/anvil-explorer-sheets/constants.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# CHANGE THESE VALUES TO GENERATE NEW REPORTS
22
# The date of the current month to report on (yyyy-mm)
3-
CURRENT_MONTH = "2026-04"
3+
CURRENT_MONTH = "2026-05"
44
# The name of the folder in which to save the report
5-
PARENT_FOLDER_NAME = "April 2026"
5+
PARENT_FOLDER_NAME = "May 2026"
66

77
# The name of the spreadsheet with the report
88
SHEET_NAME = "AnVIL Explorer"

analytics/hca-explorer-sheets/constants.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# CHANGE THESE VALUES TO GENERATE NEW REPORTS
22
# The date of the current month to report on (yyyy-mm)
3-
CURRENT_MONTH = "2026-04"
3+
CURRENT_MONTH = "2026-05"
44
# The name of the folder in which to save the report
5-
PARENT_FOLDER_NAME = "April 2026"
5+
PARENT_FOLDER_NAME = "May 2026"
66

77
# The name of the spreadsheet with the report
88
SHEET_NAME = "HCA Explorer"

analytics/hca-explorer-sheets/generate_static_site.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@ def resolve_project_titles(data):
4848
"file_downloads_position": 3,
4949
"event_counts": [
5050
{"label": "Export to Terra\n(Single Project)", "event_key": "dataset_analyze_in_terra_requested"},
51-
{"label": "Export to Terra\n(Cross-Dataset)", "event_key": "index_analyze_in_terra_requested"},
51+
{"label": "Export to Terra\n(Cross-Project)", "event_key": "index_analyze_in_terra_requested"},
5252
{"label": "curl Command\n(Single Project)", "event_key": "dataset_bulk_download_requested"},
53-
{"label": "curl Command\n(Cross-Dataset)", "event_key": "index_bulk_download_requested"},
53+
{"label": "curl Command\n(Cross-Project)", "event_key": "index_bulk_download_requested"},
5454
{"label": "File Manifest\n(Single Project)", "event_key": "dataset_file_manifest_requested"},
55-
{"label": "File Manifest\n(Cross-Dataset)", "event_key": "index_file_manifest_requested"},
55+
{"label": "File Manifest\n(Cross-Project)", "event_key": "index_file_manifest_requested"},
5656
],
5757
},
5858
property_id=HCA_ID,

analytics/lungmap-analytics/sheets/constants.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# CHANGE THESE VALUES TO GENERATE NEW REPORTS
22
# The date of the current month to report on (yyyy-mm)
3-
CURRENT_MONTH = "2026-04"
3+
CURRENT_MONTH = "2026-05"
44
# The name of the folder in which to save the report
5-
PARENT_FOLDER_NAME = "April 2026"
5+
PARENT_FOLDER_NAME = "May 2026"
66

77
# The name of the spreadsheet with the report
88
SHEET_NAME = "Lungmap Data Browser"

analytics/lungmap-analytics/sheets/generate_static_site.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@ def resolve_project_titles(data):
4848
"file_downloads_position": 3,
4949
"event_counts": [
5050
{"label": "Export to Terra\n(Single Project)", "event_key": "dataset_analyze_in_terra_requested"},
51-
{"label": "Export to Terra\n(Cross-Dataset)", "event_key": "index_analyze_in_terra_requested"},
51+
{"label": "Export to Terra\n(Cross-Project)", "event_key": "index_analyze_in_terra_requested"},
5252
{"label": "curl Command\n(Single Project)", "event_key": "dataset_bulk_download_requested"},
53-
{"label": "curl Command\n(Cross-Dataset)", "event_key": "index_bulk_download_requested"},
53+
{"label": "curl Command\n(Cross-Project)", "event_key": "index_bulk_download_requested"},
5454
{"label": "File Manifest\n(Single Project)", "event_key": "dataset_file_manifest_requested"},
55-
{"label": "File Manifest\n(Cross-Dataset)", "event_key": "index_file_manifest_requested"},
55+
{"label": "File Manifest\n(Cross-Project)", "event_key": "index_file_manifest_requested"},
5656
],
5757
},
5858
property_id=LUNGMAP_ID,

0 commit comments

Comments
 (0)