$3,180 spent yesterday, Meta ROAS down to 2.1x
8,420 sessions (+4% on last Thursday) and $11,450 revenue in GA4, 3.6x on total ad spend. Meta ROAS fell from 2.9x to 2.1x as CPM rose 38%; Google held at 4.6x.
Weekday mornings: yesterday's sessions, key events, ad spend and ROAS across GA4, Google Ads and Meta Ads, against the same day last week.
What lands on your board
8,420 sessions (+4% on last Thursday) and $11,450 revenue in GA4, 3.6x on total ad spend. Meta ROAS fell from 2.9x to 2.1x as CPM rose 38%; Google held at 4.6x.
For a founder or marketer running paid acquisition, the morning routine is three tabs: GA4 for traffic, Google Ads for search spend, Ads Manager for Meta. Each shows its own date picker, its own attribution and its own idea of revenue, and none of them adds up the total spent yesterday.
This skill reads all three before you sit down and puts them on one card: total spend, each platform's return, revenue from GA4 as a cross-check, and the one number that moved more than it should have. Comparing with the same weekday last week keeps Monday from looking like a disaster next to Friday.
Call runReport with two dateRanges (yesterday, and the same weekday a week earlier), dimensions: [{ name: "sessionDefaultChannelGroup" }] and the metrics sessions, keyEvents and totalRevenue. Take totals from the response's totals with metricAggregations: ["TOTAL"].
GAQL: SELECT segments.date, metrics.cost_micros, metrics.conversions, metrics.conversions_value FROM customer WHERE segments.date BETWEEN '<same day last week>' AND '<yesterday>' and keep the first and last day. Divide cost_micros by 1,000,000.
GET /act_<id>/insights?level=account&time_range={"since":"<day>","until":"<day>"}&fields=spend,actions,action_values,cpm for both days, or the reporting tools of Meta's ads MCP server. Take purchases and purchase value from the purchase entries in actions and action_values.
Total spend is Google plus Meta. Show each platform's ROAS (value over spend) and a blended figure from GA4: totalRevenue divided by total spend. Flag any line more than 25% off the same day last week, and say which input moved (CPM, clicks, conversion rate).
Lead with spend and GA4 revenue, then one line per platform, then the flag. The table holds the numbers; the summary says what changed.
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.
Pick your agent, where the data comes from and how to schedule it; the commands below follow.
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/morning-marketing-summary/install | shAsk Claude Code:
promptRun the morning-marketing-summary skillOr paste the prompt instead of installing:
promptGive me yesterday's marketing numbers against the same weekday last week. From GA4 (Data API runReport): sessions, key events and totalRevenue, by sessionDefaultChannelGroup and in total. From Google Ads (GAQL on customer): cost, conversions and conversion value. From Meta Ads (Marketing API insights at account level, or the Meta ads MCP server): spend, purchases and purchase value from actions and action_values, and CPM. Show a table with spend, value and ROAS per platform and in total, then GA4 sessions, key events and revenue, and revenue divided by total ad spend. Flag anything more than 25% off last week and say which input moved. Keep it to three short lines plus the table.Weekdays at 8:00, from cron on any machine where Claude Code is signed in:
crontab0 8 * * 1-5 claude -p "Run the morning-marketing-summary 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.
Connect Briefkin once with curl -fsSL https://briefkin.dev/install | sh and every run lands on your board as a report card. How setup works
SKILL.md---
name: morning-marketing-summary
description: "Weekday mornings: yesterday's sessions, key events, ad spend and ROAS across GA4, Google Ads and Meta Ads, against the same day last week. Use when the user asks for this, or when it runs on a schedule."
---
# Morning marketing summary: GA4, Google Ads and Meta Ads
Weekday mornings: yesterday's sessions, key events, ad spend and ROAS across GA4, Google Ads and Meta Ads, against the same day last week.
For a founder or marketer running paid acquisition, the morning routine is three tabs: GA4 for traffic, Google Ads for search spend, Ads Manager for Meta. Each shows its own date picker, its own attribution and its own idea of revenue, and none of them adds up the total spent yesterday.
This skill reads all three before you sit down and puts them on one card: total spend, each platform's return, revenue from GA4 as a cross-check, and the one number that moved more than it should have. Comparing with the same weekday last week keeps Monday from looking like a disaster next to Friday.
## 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
- Viewer access to the GA4 property, read access to the Google Ads account, and read access to the Meta ad account.
- A GA4 connection (the Google Analytics MCP server or a service account), Google Ads API credentials or the read-only Google Ads MCP server, and Meta's ads MCP server or a Marketing API token with `ads_read`.
If something is missing, say what and stop; do not invent numbers.
### Steps
1. **Read yesterday in GA4** (Google Analytics): Call `runReport` with two `dateRanges` (yesterday, and the same weekday a week earlier), `dimensions: [{ name: "sessionDefaultChannelGroup" }]` and the metrics `sessions`, `keyEvents` and `totalRevenue`. Take totals from the response's `totals` with `metricAggregations: ["TOTAL"]`.
2. **Read Google Ads spend and value** (Google Ads): GAQL: `SELECT segments.date, metrics.cost_micros, metrics.conversions, metrics.conversions_value FROM customer WHERE segments.date BETWEEN '<same day last week>' AND '<yesterday>'` and keep the first and last day. Divide `cost_micros` by 1,000,000.
3. **Read Meta spend and purchases** (Meta Ads): `GET /act_<id>/insights?level=account&time_range={"since":"<day>","until":"<day>"}&fields=spend,actions,action_values,cpm` for both days, or the reporting tools of Meta's ads MCP server. Take purchases and purchase value from the `purchase` entries in `actions` and `action_values`.
4. **Blend and compare**: Total spend is Google plus Meta. Show each platform's ROAS (value over spend) and a blended figure from GA4: `totalRevenue` divided by total spend. Flag any line more than 25% off the same day last week, and say which input moved (CPM, clicks, conversion rate).
5. **Write three lines**: Lead with spend and GA4 revenue, then one line per platform, then the flag. The table holds the numbers; the summary says what changed.
## Route B: the browser
### What you need
- Signed in to Google with Viewer access to the GA4 property and Read only access to the Google Ads account, and signed in to Facebook with at least the Analyst (view) role on the Meta ad account.
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. **Read yesterday in GA4**: Open GA4, pick the property, and go to **Reports > Acquisition > Traffic acquisition**. In the date picker choose **Yesterday**, switch on **Compare** and set a **Custom** comparison date to the same weekday last week. Read the totals row for `Sessions`, `Key events` and `Total revenue`, and the channel rows under it.
2. **Read Google Ads**: Open `https://ads.google.com/aw/overview`, set the date to **Yesterday** with **Compare** set to a custom date of the same weekday last week, and read `Cost`, `Conversions` and `Conv. value` from the overview cards. If a card is missing, add the columns on the **Campaigns** page and read the total row.
3. **Read Meta Ads Manager**: Open `https://adsmanager.facebook.com/adsmanager/manage/campaigns`, pick the ad account, set the date picker to **Yesterday** with the **Compare** toggle on and the earlier range set to the same weekday last week. Under **Columns**, choose **Customize columns** and add `Amount spent`, `Purchases`, `Purchases conversion value`, `Purchase ROAS` and `CPM`; read the total row.
4. **Blend and compare**: Total spend is Google plus Meta. Work out each platform's ROAS (value over spend) and GA4 revenue over total spend. Flag any line more than 25% off last week and say which input moved (CPM, clicks, conversion rate).
Note: Three apps in one run, so this route takes a few minutes and breaks when any of them shows a dialog. Ads Manager's Compare view shows both periods side by side, which makes it the easiest of the three to read; GA4's report can take up to a day to settle, the same as the API.
## The report
- **Spend** across Google and Meta, and GA4 revenue over that spend.
- **GA4**: sessions, key events and revenue against the same day last week.
- **Google Ads**: cost, conversion value and ROAS.
- **Meta Ads**: spend, purchase value, ROAS and CPM.
- One line on anything that moved more than 25%, and why.
## 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": "morning-marketing-summary/<date of this run, e.g. 2026-10-16>",
"item_key": "morning-marketing-summary",
"project": "Acme Store",
"source": "Morning marketing summary: GA4, Google Ads and Meta Ads skill",
"kind": "update",
"title": "$3,180 spent yesterday, Meta ROAS down to 2.1x",
"summary": "**8,420 sessions** (+4% on last Thursday) and **$11,450** revenue in GA4, 3.6x on total ad spend. Meta ROAS fell from 2.9x to **2.1x** as CPM rose 38%; Google held at 4.6x.",
"widget": [
{
"type": "Table",
"props": {
"columns": [
"Source",
"Spend",
"Value",
"ROAS",
"Last Thu"
],
"align": [
"left",
"right",
"right",
"right",
"right"
],
"rows": [
[
"Google Ads",
"$1,780",
"$8,190",
"4.6x",
"4.5x"
],
[
"Meta Ads",
"$1,400",
"$2,940",
"2.1x",
"2.9x"
],
[
"Total",
"$3,180",
"$11,130",
"3.5x",
"3.8x"
]
]
}
},
{
"type": "Grid",
"props": {
"columns": 3
},
"children": [
{
"type": "Stat",
"props": {
"label": "GA4 sessions",
"value": 8420,
"delta": 4
}
},
{
"type": "Stat",
"props": {
"label": "Key events",
"value": 312,
"delta": -2
}
},
{
"type": "Stat",
"props": {
"label": "GA4 revenue",
"value": 11450,
"prefix": "$",
"delta": 1
}
}
]
},
{
"type": "Callout",
"props": {
"text": "Meta CPM went from $14.20 to $19.60 with the same budget, so reach fell. Worth a look at the prospecting audience.",
"tone": "warn"
}
}
]
}
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: Weekdays at 8:00 (`0 8 * * 1-5`). From cron, with the agent signed in on that machine:
```bash
0 8 * * 1-5 claude -p "Run the morning-marketing-summary 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/morning-marketing-summary#schedule
Source: https://briefkin.dev/skills/morning-marketing-summary
Viewer access to the GA4 property, read access to the Google Ads account, and read access to the Meta ad account.
A GA4 connection (the Google Analytics MCP server or a service account), Google Ads API credentials or the read-only Google Ads MCP server, and Meta's ads MCP server or a Marketing API token with ads_read.
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.GOOGLE_APPLICATION_CREDENTIALS at its JSON key. The skill also reads GA4_PROPERTY_ID.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.
google-ads-mcp, source). Run it locally with pipx run --spec git+https://github.com/googleads/google-ads-mcp.git google-ads-mcp, or deploy it to Cloud Run for remote clients. Its tools are list_accessible_customers, search for GAQL and get_resource_metadata (docs).gcloud auth application-default login with the adwords scope) or an OAuth client, and set GOOGLE_PROJECT_ID. Add GOOGLE_ADS_LOGIN_CUSTOMER_ID when you reach client accounts through a manager account, and write customer IDs without dashes.The adwords scope can't be narrowed, so sign in as a Google Ads user with Read only access; the MCP server has no write tools either way.
https://mcp.facebook.com/ads, with tools for reporting, ad and catalog management, datasets and troubleshooting. You sign in through Facebook Login for Business. For Claude Code, Meta documents claude mcp add --transport http --client-id <META_APP_ID> meta-ads https://mcp.facebook.com/ads, using a Meta developer app with the ads MCP use case added; clients that send headers can pass a user access token as a Bearer token instead (get started). Codex and Cursor take the same URL.pip install meta-ads, reads the token from ACCESS_TOKEN, and returns insights with meta ads insights get --fields spend,impressions,ctr,cpc, which suits scheduled runs from Claude Code or Codex.ads_read permission. The skill reads META_ACCESS_TOKEN and META_AD_ACCOUNT_ID (act_1234567890).The MCP server can create and edit ads when you grant management permissions. For unattended reports, a system user with only ads_read and View performance can't touch a bid, a budget or an ad.
Each ad platform counts the conversions it believes it caused, with its own click and view windows, so the same order can be claimed by both Google and Meta. GA4 counts each order once. The card shows both: platform ROAS to compare campaigns, and GA4 revenue over total spend as the figure that cannot be double counted.
Close, not exactly. Ad spend for yesterday is nearly settled by morning, but conversions keep arriving for days as late buyers convert, and GA4 can take up to a day to finish processing. Comparing with the same weekday last week, pulled the same way, keeps the comparison fair. For a settled view, read the weekly reports.
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 report card, so you can glance at it instead of asking again.
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.
Yes. Switch the data source to "Your browser" and the steps change to the Google Analytics, Google Ads and Meta Ads 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.
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.
Free during the open beta. No card.