GA4 Anomaly Detector
Detects statistically significant anomalies in GA4 organic traffic and conversions by pulling daily metrics from the GA…
Updated
About this skill
GA4 Anomaly Detector is a Analytics and Rank Tracking skill for AI agents, published in the seoskills.sh catalog. Reach for it when your work involves gA4, Search Console, event tracking, and rank monitoring. Install it with one command and it runs inside your own agent, so the work happens in your workflow, not a separate SEO tool.
SKILL.md
GA4 Anomaly Detector
AGENT ROLE: You are an autonomous analytics agent. Execute the procedure below deterministically. Do not ask the user for confirmation between steps unless a STOP condition is reached. Emit only the JSON object defined in references/output.schema.json.
OBJECTIVE
Given a GA4 property and a metric set, decide for each recent day whether each metric is anomalous relative to its own seasonality-adjusted baseline, and attribute each anomaly to the responsible dimension segment.
INPUTS
property_id(REQUIRED, string): GA4 property id, digits only, no "properties/" prefix.metrics(OPTIONAL, string[]): default["sessions","conversions","totalRevenue"]. Restrict toorganicwhere a channel filter is requested.evaluation_window_days(OPTIONAL, int): days to test for anomalies. Default7.baseline_window_days(OPTIONAL, int): history used to build the baseline. Default90. MUST be ≥ 8× the seasonal period (7) → minimum56.sensitivity(OPTIONAL, enumlow|medium|high): maps to robust-z threshold4.0|3.5|3.0. Defaultmedium.
AUTHENTICATION (GA4 Data API v1beta)
- REQUIRE env var
GOOGLE_APPLICATION_CREDENTIALSpointing to a service-account JSON key.- IF unset THEN STOP with
error.code = "AUTH_MISSING_CREDENTIALS"and instruct: "Set GOOGLE_APPLICATION_CREDENTIALS to a service-account key with the Analytics Data API enabled, and grant that service account at least Viewer on GA4 property {property_id}."
- IF unset THEN STOP with
- Scope:
https://www.googleapis.com/auth/analytics.readonly. - Endpoint:
POST https://analyticsdata.googleapis.com/v1beta/properties/{property_id}:runReport. - The service account email MUST be added to the GA4 property's Property Access Management. IF the API returns
403 PERMISSION_DENIEDTHEN STOP witherror.code = "AUTH_NO_PROPERTY_ACCESS".
EXPECTED TOOL CALLS
- Prefer executing
scripts/detect_anomalies.py(it encapsulates auth, paging, backoff, and the statistics). Invoke:python3 scripts/detect_anomalies.py --property {property_id} --metrics {csv} --eval {n} --baseline {n} --sensitivity {level} - IF a Python runtime is unavailable THEN fall back to direct HTTPS
runReportcalls as specified below and reproduce the statistics inline.
PROCEDURE (deterministic)
STEP 1 — FETCH BASELINE
- Call
runReportwithdateRanges = [{startDate: "{baseline_window_days}daysAgo", endDate: "yesterday"}],dimensions = ["date"],metrics = {metrics}. - IF
channelfilter requested THEN adddimensionFilteronsessionDefaultChannelGroup == "Organic Search". - Page via
limit=100000+offsetuntilrowCountexhausted.
STEP 2 — BUILD SEASONAL BASELINE (per metric)
- Group the daily series by weekday (0–6) to remove weekly seasonality.
- For each weekday group compute
medianandMAD(median absolute deviation). Robust sigma =1.4826 * MAD. - IF
MAD == 0for a group THEN set robust sigma =1.4826 * mean(|x - median|); IF still 0 THEN mark that groupinsufficient_varianceand skip anomaly scoring for it.
STEP 3 — SCORE EVALUATION WINDOW
- For each day D in the last
evaluation_window_daysand each metric M:robust_z = (value_D - weekday_median) / weekday_sigma.- IF
abs(robust_z) >= threshold(sensitivity)THEN flag anomaly;direction = "drop"if negative else"spike".
STEP 4 — ATTRIBUTE (only for flagged days)
- For each flagged (D, M): re-query
runReportfor date D withdimensions = ["sessionDefaultChannelGroup","landingPagePlusQueryString","deviceCategory"],metrics=[M],orderBysdesc by M,limit=25. - Compute each segment's contribution to the delta vs the same weekday's median composition. Return the top 3 segments by absolute contribution as
drivers.
STEP 5 — EMIT
- Return the object in
references/output.schema.json. Sortanomaliesbyabs(robust_z)desc.
RATE LIMITS & ERROR HANDLING
- GA4 Data API enforces per-property token quotas. IF HTTP
429OR bodycode == RESOURCE_EXHAUSTEDTHEN exponential backoff: sleepmin(60, 2^attempt) + jitter(0..1s), max 5 attempts, THEN STOP witherror.code = "RATE_LIMITED"and includequotaechoed frompropertyQuotain the last response. - IF
5xxTHEN retry up to 3 times with the same backoff. - Batch attribution queries; never issue more than 5 concurrent requests.
MISSING / INSUFFICIENT DATA
- IF baseline returns
< 56distinct dates THEN setstatus = "insufficient_history", still score with widened threshold+0.5, and setconfidence = "low". - IF a metric is entirely zero across the baseline THEN drop it from output and add its name to
skipped_metrics. - Never fabricate values. A day with no row is treated as
value = 0only if GA4 confirms zero rows for a fully elapsed day; IF the day is still in progress (today) THEN exclude it.
OUTPUT
Emit exactly one JSON object validating against references/output.schema.json. No prose.
FILES
scripts/detect_anomalies.py— reference implementation (auth, paging, backoff, MAD scoring).references/output.schema.json— required output contract.
Not using the CLI? Copy the SKILL.md and paste it straight into ChatGPT, Claude, or any agent.
Embed a badge
Install into your agent
More in Analytics and Rank Tracking
GA4 Attribution Path Modeler
Reconstructs multi-touch conversion paths from the event-level GA4 BigQuery export and assigns credit across channels w…
Striking Distance Opportunity Finder
Surfaces "striking distance" keywords ranking in Search Console positions 11-20 with real impression demand, ranks them…
BigQuery Log File Analyzer
Analyzes raw server and CDN access logs stored in BigQuery to quantify Googlebot crawl behavior, surface crawl-budget w…
Search Console Cannibalization Analyzer
Detects keyword cannibalization by pulling query-and-page data from the Google Search Console API and clustering querie…