---
name: google-analytics-monthly-report
description: "On the 2nd of each month: last month's GA4 traffic, users and key events against the month before and the same month last year, in plain words. Use when the user asks for this, or when it runs on a schedule."
---

# GA4 monthly traffic report

On the 2nd of each month: last month's GA4 traffic, users and key events against the month before and the same month last year, in plain words.

Agencies and in-house marketers spend the first morning of each month rebuilding the same report: pick the dates, set the comparison, screenshot the channel chart, and write three sentences a client or a board member will actually read. The numbers are quick. The sentences are what eat the morning.

The agent drafts both. It compares the month with the one before and with the same month last year, so a seasonal dip is not mistaken for a problem, and it writes the summary in words that someone outside marketing can follow.

## 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 each GA4 property you report on; agencies can list several property IDs, one card per client.
- Data API access for the agent, through an Analytics MCP server, a connector, or a service account added to every property in the list.

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

### Steps

1. **Pull the month and its comparisons** (Google Analytics): Call `runReport` with three `dateRanges`: last calendar month, the month before, and the same month a year earlier. Metrics: `sessions`, `activeUsers`, `newUsers`, `engagementRate`, `keyEvents` and, for a store, `totalRevenue`.
2. **Break it down** (Google Analytics): Run the same ranges by `sessionDefaultChannelGroup`, then the top 10 by `landingPagePlusQueryString`, then the top 5 by `deviceCategory` and by `country`, so each section of the report has its own small table.
3. **Check for tracking gaps first** (Google Analytics): Look at daily `sessions` (dimension `date`) for the month before writing anything. A run of days near zero means the tag broke, and the report should say so instead of explaining a drop that never happened.
4. **Write it for a reader outside marketing**: Three to five sentences up top: what happened, why, and what comes next. Then the tables. Give changes in percent, round large numbers, and give engagement rate changes in percentage points.

## Route B: the browser

### What you need

- Signed in to Google with the Viewer role on each GA4 property you report on; an agency account switches property between clients with the picker at the top left.

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. **Check for tracking gaps first**: Pick the property, open Reports > Acquisition > Traffic acquisition, set the date range to `Last month` and look at the chart with Day granularity. A run of days near zero means the tag broke; the report should say so before it explains anything.
2. **Read the headline against last month**: Open Reports > Reports snapshot with `Last month`, switch on Compare with `Previous period (match day of week)` and Apply. Read Active users, New users, Sessions, Engagement rate, Key events and, for a store, Total revenue with their change.
3. **Repeat against last year**: Change the comparison to `Previous year` and read the same numbers again. Keep both sets: a dip against last month that also happened last year is seasonal.
4. **Collect the breakdowns**: With the same dates, read Sessions by `Session default channel group` in Traffic acquisition, the top 10 rows in Reports > Engagement > Landing page, the top 5 in Reports > Tech > Tech details (`Device category`) and in Reports > User > User attributes > Demographic details (`Country`).
5. **Write for a reader outside marketing**: Three to five sentences up top: what happened, why, what comes next. Then the tables. Changes in percent, large numbers rounded, engagement rate changes in percentage points.

Note: Run it on the 2nd or later so the last day of the month is processed. For several clients, repeat the same steps per property; the comparisons are the ones the snapshot already draws, so the browser route works well for one or two properties and gets long beyond that.

## The report

- **Summary**: three to five sentences on the month for a reader who never opens GA4.
- **Headline table**: sessions, active users, new users, engagement rate and key events, against last month and last year.
- **Channels**: sessions by default channel group.
- **Top landing pages**, **devices** and **countries**, top entries only.
- **Data notes**: tracking gaps or settings changes that affect the numbers.

## 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-monthly-report/<date of this run, e.g. 2026-10-16>",
  "item_key": "google-analytics-monthly-report",
  "project": "example.com",
  "source": "GA4 monthly traffic report skill",
  "kind": "update",
  "title": "September: sessions up 7%, key events up 9%",
  "summary": "September brought **118,400 sessions** (+7% on August, +31% on September 2025) and **4,620 key events** (+9%). Organic Search carried the growth; Paid Search stayed flat after the budget cut on the 12th.",
  "widget": [
    {
      "type": "Table",
      "props": {
        "columns": [
          "Metric",
          "September",
          "vs August",
          "vs Sep 2025"
        ],
        "align": [
          "left",
          "right",
          "right",
          "right"
        ],
        "rows": [
          [
            "Sessions",
            118400,
            "+7%",
            "+31%"
          ],
          [
            "Active users",
            86900,
            "+6%",
            "+28%"
          ],
          [
            "New users",
            64200,
            "+5%",
            "+24%"
          ],
          [
            "Engagement rate",
            "60.8%",
            "+1.2 pts",
            "+3.5 pts"
          ],
          [
            "Key events",
            4620,
            "+9%",
            "+44%"
          ]
        ]
      }
    },
    {
      "type": "Text",
      "props": {
        "text": "Sessions by channel",
        "variant": "heading"
      }
    },
    {
      "type": "Bars",
      "props": {
        "items": [
          {
            "label": "Organic Search",
            "value": 51300
          },
          {
            "label": "Direct",
            "value": 25900
          },
          {
            "label": "Paid Search",
            "value": 17800
          },
          {
            "label": "Referral",
            "value": 9400
          },
          {
            "label": "Email",
            "value": 7600
          },
          {
            "label": "Organic Social",
            "value": 6400
          }
        ]
      }
    }
  ]
}
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: 2nd of the month at 9:00 (`0 9 2 * *`). From cron, with the agent signed in on that machine:

```bash
0 9 2 * * claude -p "Run the google-analytics-monthly-report 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-monthly-report#schedule

Source: https://briefkin.dev/skills/google-analytics-monthly-report
