How the skill works: your agent reads 29 days of daily sessions from Google Analytics; ga4 property id, alert when sessions drop by from What you tell it, every day at 10:00, and gives you a question for you and a telegram ping and the report in the chat.
Reads
Google Analytics29 days of daily sessions
What you tell itGA4 property ID, Alert when sessions drop by
reads
Your agentClaude Code, Codex, Cursor or GeminiEvery day at 10:00
posts
You get
A question for youOn your board, answered with a tap
A Telegram pingOnly when it needs your answer, if you connect Telegram
The report in the chatEvery run, with or without Briefkin
What you get
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.
The card on the right is a sample. Yours shows your own numbers and updates in place every run.
What lands on your board
Your boardEvery day at 10:00
example.comGA4 traffic drop alert · Claude Code
Sessions 36% below a normal Thursday
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?
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.
Channel
Yesterday
Thursday avg
Change
Paid Search
70
1,480
-95%
Organic Search
1,380
1,420
-3%
Direct
730
760
-4%
Referral
175
180
-3%
Email
160
150
+7%
Organic Social
115
120
-4%
Total
2,630
4,110
-36%
An example with made-up numbers. Your agent posts your real ones.
What it does
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.
How it works
1Pull 29 days of daily sessions
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
2Compare 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.
3Find 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, rerun by deviceCategory and hostName: an even drop usually means the tag stopped firing on some pages or browsers.
4
4Ask, 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.
Post it to the board
With BRIEFKIN_TOKEN set, the agent sends the result as one card that updates in place every run. Without it, you get the report in the chat.
Install and run it
Pick your agent, where the data comes from and how to schedule it; the commands below follow.
Agent
Data
Schedule
Install the skill
One command. It puts the SKILL.md in ~/.claude/skills and in ~/.agents/skills, which Codex, Cursor, Gemini CLI, Copilot CLI and OpenCode read too.
shellcurl -fsSL https://briefkin.dev/skills/google-analytics-traffic-drop-alert/install | sh
Run it
Ask Claude Code:
promptRun the google-analytics-traffic-drop-alert skill
Or paste the prompt instead of installing:
promptCheck my GA4 property with the Analytics Data API: get daily sessions by sessionDefaultChannelGroup from 29 days ago to yesterday. Compare yesterday's total with the average of the four earlier days that fall on the same weekday. If yesterday is 30% or more below that average (and the average is at least 300 sessions), show a table of each channel's sessions yesterday, its weekday average and the change, say which channel lost the most, and tell me whether it looks like a source problem (one channel) or a tracking problem (every channel down by a similar share). If it is not a drop, just give me yesterday's sessions and say they are in the normal range.
Put it on a schedule
Every day at 10:00, from cron on any machine where Claude Code is signed in:
crontab0 10 * * * claude -p "Run the google-analytics-traffic-drop-alert skill"
Add it with crontab -e. A laptop asleep at that time runs it when it wakes if you use launchd or Task Scheduler instead; GitHub Actions works for the API route.
Send it to your board
Connect Briefkin once with curl -fsSL https://briefkin.dev/install | sh and every run lands on your board as a question for you. How setup works
SKILL.md---
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
What your agent needs
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.
Connecting Google Analytics
Google Analytics MCP server, Google's own open-source server (analytics-mcp on PyPI, source). It runs locally with pipx run analytics-mcp, offers run_report, run_realtime_report and get_account_summaries, and Google labels it experimental.
Data API with a service account. Enable the Google Analytics Data API in a Google Cloud project, create a service account, add its email as a Viewer on the GA4 property, and point GOOGLE_APPLICATION_CREDENTIALS at its JSON key. The skill also reads GA4_PROPERTY_ID.
Your own Google login.gcloud auth application-default login --scopes https://www.googleapis.com/auth/analytics.readonly,https://www.googleapis.com/auth/cloud-platform --client-id-file=client.json gives the MCP server or a script your user's access without a key file.
Request only analytics.readonly and keep the service account at Viewer: none of these reports needs Editor.
Questions
Will a public holiday set it off?
It can, because a holiday Monday is compared with four ordinary Mondays. Reply "Known" and the agent notes the date. To avoid it, list your holidays in the skill and the agent will skip them or compare each with the same holiday last year.
Is yesterday complete by 10:00?
Mostly. GA4 can take up to a day to finish processing, so the last hours may still arrive. Mid-morning is a fair trade between early warning and false alarms. When the gap is within a few points of 30%, the agent checks again an hour later before it asks.
Do I need Briefkin to use the GA4 traffic drop alert skill?
No. The skill runs with your own agent and gives you the report in the chat. With a Briefkin token set, each run also posts it to your board as a asks you, so you can glance at it instead of asking again.
Which agents can run it?
Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot CLI, OpenCode, Windsurf and Amp all read SKILL.md files. The install command puts it in ~/.claude/skills and ~/.agents/skills, where they look. ChatGPT, the Claude app and Grok take the prompt instead. Pick your agent under "Install and run it" and the commands change to match.
Can it work without an API or MCP server, from my browser?
Yes. Switch the data source to "Your browser" and the steps change to the Google Analytics pages themselves: the agent opens analytics.google.com/analytics/web in a browser you are signed in to and reads the numbers off the page. Claude Code, Codex, Cursor, Claude app and ChatGPT can drive a browser out of the box; Gemini CLI, Copilot CLI and OpenCode need a Playwright or Chrome DevTools MCP server first. It is slower than the API and needs you signed in, so it suits a report you run by hand or from a scheduler on your own computer.
Answer your agents from one board, or from Telegram
Skills are free to use with any agent. Briefkin is where their results land: one board for every report, number and question your agents send, with a ping when something needs you.