---
name: google-analytics-traffic-drop-alert
description: "Every morning the agent checks yesterday's GA4 sessions against the same weekday's average and asks you to look when traffic fell 30% or more. Use when the user asks for this, or when it runs on a schedule."
---

# GA4 traffic drop alert

Every morning the agent checks yesterday's GA4 sessions against the same weekday's average and asks you to look when traffic fell 30% or more.

Traffic rarely falls off a cliff, and when it does the cause is usually mundane: a deploy that dropped the tag, a paused campaign, a new consent banner. The trouble is that nobody opens GA4 on a quiet Tuesday, so the dip turns up a week later in the monthly numbers.

This skill looks every morning. On a normal day it updates the card with yesterday's number and asks nothing. When sessions fall 30% or more below what that weekday usually brings, it asks one question, already narrowed to the channel or device where the visits went missing.

## Two ways to get the data

Use the API or MCP route when you have an MCP server, a CLI or an API token for the app. Otherwise, if you can drive a browser the user is signed in to (Claude in Chrome, a Playwright or Chrome DevTools MCP server), use the browser route. Say which one you used.

## Route A: API or MCP server

### What you need

- The Viewer role on the GA4 property; the alert reads sessions and nothing else.
- Access to the Analytics Data API through an Analytics MCP server, a connector, or a service account key in `GOOGLE_APPLICATION_CREDENTIALS`.

If something is missing, say what and stop; do not invent numbers.

### Steps

1. **Pull 29 days of daily sessions** (Google Analytics): Call `runReport` from `29daysAgo` to `yesterday` with the dimensions `date` and `sessionDefaultChannelGroup` and the metric `sessions`. Dates come back in the property's time zone. The range covers yesterday and the same weekday in each of the four weeks before.
2. **Compare with the weekday baseline**: Average the four earlier days that share yesterday's weekday, for the total and for each channel. It is a drop when yesterday's total is 30% or more below that average and the average is at least 300 sessions, so tiny sites do not alert on noise.
3. **Find where the sessions went** (Google Analytics): Rank channels by sessions lost. If one channel holds most of the gap, its source is the likely cause. If every channel fell by a similar share, rerun by `deviceCategory` and `hostName`: an even drop usually means the tag stopped firing on some pages or browsers.
4. **Ask, or stay quiet**: On a drop, post an action card with the gap, the channel table and a question about the likely cause. On a normal day, update the same card with yesterday's sessions and no ask, so the board shows the check ran.

## Route B: the browser

### What you need

- Signed in to Google with the Viewer role on the GA4 property.

If something is missing, say what and stop; do not invent numbers.

### Steps

Start at https://analytics.google.com/analytics/web/. The user is signed in already; never type passwords or codes, and ask if a sign-in page appears.

1. **Open Traffic acquisition with 29 days of data**: Pick the property and go to Reports > Acquisition > Traffic acquisition. In the date picker set a custom range from 29 days ago to yesterday and Apply; leave Compare off.
2. **Break the table down by day**: Click the `+` next to `Session default channel group` and add `Date` as the secondary dimension. Set Rows per page to `250` so every channel-day pair is on one page, or use Share this report > Download file.
3. **Build the weekday baseline**: For yesterday's weekday, take the four earlier dates with the same weekday and average Sessions per channel and in total. It is a drop when yesterday is 30% or more below that average and the average is at least 300 sessions.
4. **Find where the sessions went**: Rank channels by sessions lost. If one channel holds most of the gap, its source is the likely cause. If every channel fell by a similar share, change the primary dimension to `Device category` (Reports > Tech > Tech details) and check `Hostname` in an exploration; an even drop usually means the tag stopped firing somewhere.
5. **Report, or say all is normal**: On a drop, give the gap, the channel table and the likely cause, and ask what to check first. On a normal day, just yesterday's sessions and that they are in range.

Note: Yesterday can still be filling in during the morning, so a borderline gap deserves a second look an hour later. A browser agent has to be started each morning; it will not wake itself, so this route suits a person who checks on demand rather than a daily alert.

## The report

- **Yesterday's sessions** against the average of the last four same weekdays, and the gap in percent.
- **Channel table**: yesterday, the weekday average and the change for each default channel group.
- **Likely cause**: one channel (a source problem) or every channel at once (a tracking problem).
- The ask: what to check first, with quick replies to confirm, explain or snooze.

## Post it to Briefkin

When `BRIEFKIN_TOKEN` is set, or `~/.config/briefkin/env` exists (the installer from https://briefkin.dev/docs writes it), also send the result to the user's Briefkin board as one card. Keep the `item_key` the same on every run so the card updates in place, use a new `event_id` per run, and put today's real numbers in place of the example ones. If the request fails, say so once and carry on.

```bash
[ -n "${BRIEFKIN_TOKEN:-}" ] || . ~/.config/briefkin/env
curl -sS -X POST "${BRIEFKIN_URL:-https://briefkin.dev}/v1/events" \
  -H "authorization: Bearer $BRIEFKIN_TOKEN" \
  -H "content-type: application/json" \
  -d @- <<'JSON'
{
  "v": 1,
  "event_id": "google-analytics-traffic-drop-alert/<date of this run, e.g. 2026-10-16>",
  "item_key": "google-analytics-traffic-drop-alert",
  "project": "example.com",
  "source": "GA4 traffic drop alert skill",
  "kind": "action",
  "title": "Sessions 36% below a normal Thursday",
  "summary": "Yesterday brought **2,630 sessions** against a Thursday average of 4,110. Paid Search accounts for 1,410 of the 1,480 missing; every other channel is within 7% of normal.",
  "action": {
    "request": "Paid Search sessions fell from about 1,480 to 70. Can you check that the Google Ads campaigns are running and that billing went through?",
    "options": [
      "Checking now",
      "Known: campaigns paused",
      "Looks like tracking",
      "Snooze until Monday"
    ]
  },
  "widget": {
    "type": "Table",
    "props": {
      "columns": [
        "Channel",
        "Yesterday",
        "Thursday avg",
        "Change"
      ],
      "align": [
        "left",
        "right",
        "right",
        "right"
      ],
      "rows": [
        [
          "Paid Search",
          70,
          1480,
          "-95%"
        ],
        [
          "Organic Search",
          1380,
          1420,
          "-3%"
        ],
        [
          "Direct",
          730,
          760,
          "-4%"
        ],
        [
          "Referral",
          175,
          180,
          "-3%"
        ],
        [
          "Email",
          160,
          150,
          "+7%"
        ],
        [
          "Organic Social",
          115,
          120,
          "-4%"
        ],
        [
          "Total",
          2630,
          4110,
          "-36%"
        ]
      ]
    }
  }
}
JSON
```

Widgets come from the Briefkin catalog (https://briefkin.dev/v1/catalog). Without a token, just give the user the report.

## Run it on a schedule

Suggested: Every day at 10:00 (`0 10 * * *`). From cron, with the agent signed in on that machine:

```bash
0 10 * * * claude -p "Run the google-analytics-traffic-drop-alert skill"
# Codex: codex exec, Gemini CLI: gemini -p, Copilot CLI: copilot -p, OpenCode: opencode run
```

Or use the agent's own scheduler (Claude Code routines, Codex automations, Claude or ChatGPT scheduled tasks): https://briefkin.dev/skills/google-analytics-traffic-drop-alert#schedule

Source: https://briefkin.dev/skills/google-analytics-traffic-drop-alert
