Skill instructions
ad-creative-performance7.01 KB
View saved version →
---
name: ad-creative-performance
description: Analyze ad creative from live data: ad fatigue (rising frequency, falling CTR), creative concept tests, winning hooks and formats, and refresh recommendations for Meta, TikTok, LinkedIn and Google ads. Use when ads are tiring, a creative test needs a verdict, or the creative team needs a brief.
---
# Ad creative performance
## Workflows
### Ad fatigue and frequency check
**When to use:** the user suspects ad creatives are burning out — previously strong ads losing CTR, climbing frequency, rising CPC. Often ends with notifying the creative team about which ads need refresh.
**Platforms typically involved:** Facebook Ads (`Frequency`), TikTok Ads (`frequency`), Google Ads (`avg_impr_frequency_per_user`). LinkedIn Ads has no frequency field; compute impressions ÷ reach (`approximateUniqueImpressions`).
### Step 1 — Pull the data
> Pull the last 30 days of performance data grouped by ad name, with impressions, frequency, CTR, and CPC.
Include `ad_id` if the user will need to act on this in-platform.
Frequency can't be summed or averaged across days (daily values understate it). Pull it per ad for the recent window as a separate query and put that value in the `frequency` column of the recent-window rows before running the script.
### Step 2 — Identify fatigued ads
Use `scripts/ad_fatigue_detector.py`. Default thresholds: frequency >3.5 and CTR decline >20% week-over-week. If the user wants different thresholds, accept them and pass to the script.
### Step 3 — Visualize the fatigue landscape
The question the chart needs to answer: **which ads are fatigued, how severely, and how much spend is exposed to the problem?**
The most informative visualization for this is usually a scatter plot — frequency on the x-axis, recent CTR on the y-axis, dot size weighted by spend, dot color encoding a third dimension (CPC trend, or simply flagged vs not). Shade or label the fatigue zone explicitly. The user sees at a glance which ads are in trouble and which are still healthy.
Alternative when the user has few ads (under 10): a horizontal bar chart ranking ads by severity, with spend annotated next to each bar.
Whichever you pick, name the worst offender explicitly when surfacing the chart — don't make the user visually scan.
### Step 4 — Refresh recommendations
For each flagged ad, state what's happening (frequency X, CTR down Y%, CPC up Z%) and what to do (pause, refresh creative, refresh copy only, swap thumbnail). Prioritize by spend impact — the $5k/week ad needs attention before the $50/week one.
### Step 5 — Notify the creative team
Build the email body using `assets/creative_refresh_email.md`. The default delivery is markdown inline so the user can review and send themselves. If the user wants it as a doc, use the `docx` skill. If Gmail is connected and the user wants it as a draft, offer to save it there.
### Common variations
- **No frequency threshold known** — use 3.5 as a sensible default or compute +1 standard deviation above the account's typical range.
- **Just top 10 fatigued ads** — limit the script output and the chart to top N by spend or severity.
---
### Creative concept testing and iteration
**When to use:** the user is running a creative test (multiple variants of an ad in the same campaign) and wants to identify winners and generate new variations.
**Platforms typically involved:** Facebook Ads, LinkedIn Ads, sometimes TikTok Ads.
### Step 1 — Pull the data
> Pull the last 14 days for [campaign name] across [platforms], broken down by individual ad name and ad format.
Format matters here — is video beating static? The field differs by platform (Facebook Ads `creative_object_type`, Google Ads `AdFormatType`); name the column `ad_format` for the script. Facebook Ads also returns `creative_thumbnail_url`.
### Step 2 — Rank by efficiency
Use `scripts/cpa_ranker.py` with `--group-by ad_format` to get both: top ads by CPA and the format-level comparison.
### Step 3 — Visualize the results
Two questions to answer here, often best as two charts rather than one crowded one:
- **Which ads are winning?** A ranked horizontal bar chart sorted by CPA ascending, with format encoded as bar color.
- **Which format wins on average?** A small comparison chart with format on the x-axis and the efficiency metrics (CPA, CTR, conversion rate) on the y-axis.
The user often needs both views — "video has 18% better CPA on average, but the single best ad is a static" is a real and important finding that one chart alone can miss.
### Step 4 — Write new variations
Use `assets/ad_copy_variations.md`. Identify what's working in the winners (the hook, the angle, the audience tilt — not just the words) and preserve that. Vary CTA, framing, or proof point. Don't synonym-swap.
### Step 5 — Output the variations
Default delivery is inline markdown. If the user wants a spreadsheet they can hand to ops for upload, use the `xlsx` skill with columns for headline, body, CTA, target audience, and hypothesis.
### Common variations
- **Rank by ROAS instead of CPA** — pass `--metric roas` to the ranker.
- **New audiences vs lookalikes** — re-run with `audience` as the grouping dimension.
- **Headlines only, not body copy** — the variations template has both sections; pick the relevant one.
- **Industry benchmark CTR** — if the user wants context for whether their numbers are good, use web search to find recent industry benchmark data and overlay as a reference line on the chart.
---
## Background
Chart choices, principles and gotchas for this area: [references/performance-marketer-guide.md](references/performance-marketer-guide.md).
## Before you analyze
- Load saved targets, budgets and known context with `manage_business_context` (`action: get`) and judge results against them, not generic benchmarks.
- Query correctly: follow the `marketing-data-queries` skill for discovery, field IDs and platform quirks.
- Check tracking first. If platform conversions and GA4 or backend numbers disagree by more than 20%, or spend continues with zero conversions, say so before any optimization advice.
- Pull, then analyze, as separate steps. Run one heavy query at a time.
- Evidence discipline: treat changes on fewer than ~10 conversions as noise, ignore items under 1,000 impressions, don't call learning-phase campaigns failures, check for shared budgets before budget advice, and re-pull before conceding a disputed number.
- Answer shape: conclusion, business impact, next actions, then "How I got this" (one line per data pull).
- Helper scripts in `scripts/` take a CSV and print a table. Run them if you can execute code; otherwise compute the same thing directly. Templates in `assets/` shape the final deliverable.
## After the analysis
- Analysis only recommends. If the user wants to act (pause, budget shift, negatives), use the `campaign-management` skill, with explicit approval for each change.
- For a recurring or shareable result, offer once to publish it as a live Supermetrics Studio dashboard with `manage_dashboards` (static preview first, then the live upload).
Referenced files: 7 — file references are metadata, not package contents.
b2b-pipeline-analysis17.4 KB
View saved version →
---
name: b2b-pipeline-analysis
description: B2B demand gen analysis from live ad, GA4 and CRM data (HubSpot, Salesforce, Pipedrive): lead-gen efficiency, pipeline and revenue by channel, MQL-to-SQL by source, ABM engagement, and email plus paid funnels. Use for pipeline contribution, lead quality and ABM questions.
---
# B2b pipeline analysis
## Workflows
### Lead generation efficiency comparison
**When to use:** the user is comparing efficiency of B2B advertising platforms for lead capture, typically LinkedIn vs Facebook. Output is usually a one-page summary for the demand gen team or a leadership recommendation.
**Platforms typically involved:** LinkedIn Ads and Facebook Ads primarily. Sometimes Google Ads for B2B search.
### Step 1 — Pull the data with campaign filter
> Pull the last 60 days of campaign performance from LinkedIn Ads and Facebook Ads, filtered to campaigns containing the phrase [Lead Gen / LG_ / MQL_ / whatever the user's convention is].
The filter phrase is specific to the user's naming convention. Ask if unclear. The data needs to be at the ad / asset level, not just campaign level — different assets in the same campaign often perform very differently.
### Step 2 — Compare CPL and lead conversion rate
Use `scripts/lead_efficiency.py` (columns: `platform`, `spend`, `clicks`, `impressions`, `leads`). Outputs platform-level CPL, lead-to-click ratio, CTR, and a comparison summary. For LinkedIn Lead Gen Forms, the lead count is the `oneClickLeads` field.
### Step 3 — Visualize the comparison
The question the chart needs to answer: **which platform is more efficient, and by how much?**
A simple sorted bar chart of CPL by platform works as the primary visualization. If the user wants the multi-dimensional view, a small dashboard-style group (CPL, lead conversion rate, CTR, total leads) with the platforms side-by-side makes the trade-offs visible — sometimes the cheaper platform produces fewer leads, or the lower-CPL platform has worse lead quality. Name the trade-off explicitly when surfacing the visualization.
If the user has tagged the ad creatives, a secondary chart ranking individual ads by efficiency (across both platforms) surfaces the actual winners, which is often more useful than the platform-level average.
### Step 4 — Identify what's working in the winners
> Identify the top two best-performing ad creatives across both platforms based on conversion rate, and explain why their messaging is likely resonating with the target audience.
This is the qualitative step. Look at the winning ad copy and identify the actual angle — pain point, social proof, status, ROI claim. The output is a brief on what's resonating, which the user can take into the next round of creative.
Use `assets/lead_efficiency_summary.md` to structure the final deliverable.
### Step 5 — Output
Default delivery is markdown inline. If the user wants a Word doc, use the `docx` skill.
### Common variations
- **Add Google Ads search to the comparison** — search and social lead gen aren't directly comparable on raw CPL. Frame as "intent-driven (search) vs interruption-driven (social)" rather than head-to-head.
- **Cost per MQL, not cost per lead** — needs CRM data. If a HubSpot or Salesforce connector is active, pull MQL counts by source. Without one, ask the user how they'll get the data.
- **Compare to last quarter** — re-run for the prior 60-day window and overlay both periods on the chart.
---
### Pipeline contribution by channel
**When to use:** the user is in B2B and wants to credit marketing channels with the pipeline they actually create — not just leads. This is the single most-requested demand gen analysis when a CRM connector is available.
**Platforms typically involved:** ad platforms (LinkedIn Ads, Google Ads, Facebook Ads) + a CRM connected in Supermetrics (HubSpot, Salesforce, Pipedrive, Zoho CRM, Close CRM, Odoo CRM). Useful fields: HubSpot `deal_amount`, `deal_stage`, `original_source`; Salesforce `opportunity_amount`, `opportunity_stage_name`, `opportunity_lead_source`. Confirm exact names with `field_discovery`.
### Step 1 — Pull spend and pipeline
> Pull the last 90 days of ad spend by channel from [ad platforms]. Then pull opportunities created in the same period from [CRM], including opportunity amount, stage, and source/first-touch channel.
Confirm with the user how their CRM attributes channels to opportunities — most common patterns:
- **First-touch:** the channel that brought the contact in
- **Last-touch:** the channel of the activity immediately before opportunity creation
- **Multi-touch:** weighted across all touchpoints
State the attribution method explicitly in the output.
### Step 2 — Compute cost per opportunity and pipeline ROAS
Use `scripts/pipeline_attribution.py --spend spend.csv --opps opportunities.csv` (optional `--stage-filter`). Outputs per channel:
- Total spend
- Number of opportunities attributed
- Total pipeline value (sum of opportunity amounts)
- Cost per opportunity (CPO)
- Pipeline ROAS (pipeline value / spend)
### Step 3 — Visualize the credit
The question the chart needs to answer: **which channels create the pipeline, and at what cost?**
A useful primary visualization is a paired bar chart per channel: spend (one bar) and pipeline created (second bar, often on a secondary axis since the scales differ). Channels where the pipeline bar is much taller than spend are the leverage channels.
A secondary view: stacked bar of pipeline value by channel, sorted by total. Surfaces which channels concentrate vs spread their pipeline contribution.
### Step 4 — Frame caveats
This view has limitations that need to be surfaced:
- It's not closed-won revenue, it's pipeline. Some pipeline will close; some won't.
- The attribution method shapes the rankings. First-touch credits top-of-funnel channels; last-touch credits bottom-of-funnel channels.
- Opportunities can sit in pipeline for months. The 90-day window captures opps created, not opps closed.
### Step 5 — Build the report
Use `assets/pipeline_attribution_report.md`. The audience is typically the VP of Sales or CRO; tone should be data-forward with explicit acknowledgment of attribution choices. For a recurring pipeline review, offer a live Studio dashboard (with `manage_dashboards`).
### Common variations
- **Closed-won, not pipeline** — re-run with `--stage-filter` set to the CRM's closed-won stage name. Smaller numbers, longer time lag, but more defensible. Best for quarterly reviews.
- **Win rate by channel** — additional column: of opps from this channel, what % closed? Some channels generate lots of low-quality pipeline; this surfaces it.
- **Deal size by channel** — average opportunity amount per channel. Often the highest-CPO channels generate the largest deals.
---
### MQL-to-SQL conversion rate by source
**When to use:** the user needs lead quality measurement, not just lead volume. CPL is the cheap version of this question; MQL-to-SQL conversion rate is the real answer.
**Platforms typically involved:** ad platforms + CRM (HubSpot, Salesforce). Marketing automation (Marketo via the Adobe Engage connector, Eloqua, HubSpot Marketing Email) if lead nurture is part of the journey.
### Step 1 — Pull leads, MQLs, and SQLs by source
> Pull the last 90 days of leads created from [CRM], grouped by lead source. For each lead, include whether they reached MQL status and SQL status, and the dates of each transition.
In HubSpot (`HSCON`), the lifecycle date properties (`Became a lead / marketing qualified lead / sales qualified lead date`) and `original_traffic_source` give this per contact; in Salesforce, use the Leads report with `lead_source`, `lead_status` and `lead_converted_date`. HubSpot also has aggregate counts and average days to MQL/SQL in `HS`.
The 90-day window matters — leads need time to progress through the funnel. Pulling last week's data won't show conversion rates because leads haven't had time to convert.
### Step 2 — Compute conversion rates per source
Use `scripts/mql_quality.py` (columns: `source`, `lead_created_date`, `mql_date`, `sql_date`, optional `spend` or `--spend-csv`). Outputs per source:
- Total leads
- MQL conversion rate (% of leads that became MQLs)
- SQL conversion rate (% of MQLs that became SQLs)
- Lead-to-SQL conversion rate (% of leads that became SQLs)
- Time-to-MQL (median days)
### Step 3 — Visualize quality vs volume
The question the chart needs to answer: **which sources produce high-quality leads, and which produce volume without quality?**
A scatter plot works well here: x-axis = lead volume, y-axis = MQL conversion rate. Bubble size = total spend on the source. Sources in the top-right (high volume + high quality) are the keepers; bottom-right (high volume + low quality) are the spend-too-much candidates.
A secondary view: funnel chart per source — leads → MQLs → SQLs. Visualizes where the drop-off happens per source.
### Step 4 — Diagnose
For sources with low MQL conversion, the question is whether the issue is:
- **Lead targeting** (the source brings in wrong-fit leads)
- **Lead nurture** (the leads aren't getting touched, or the nurture doesn't resonate)
- **MQL definition** (the bar is set too high)
The script doesn't diagnose this automatically — surface the question for the user to investigate.
### Step 5 — Output
Use `assets/lead_quality_diagnostic.md`. Audience: marketing operations or demand gen leadership.
### Common variations
- **Add deal-source connection** — for sources where SQLs convert, what's the average deal size? Quality has multiple dimensions.
- **Cohort by month** — recent-cohort conversion rates may differ from older cohorts. Plot trend.
- **Compare paid vs organic sources** — paid sources should have higher CPL but often have lower MQL rates because of intent quality.
---
### ABM campaign performance
**When to use:** the user runs account-based marketing (ABM) and needs to measure coverage and engagement across a defined target account list.
**Platforms typically involved:** LinkedIn Ads (the primary ABM ad platform) + CRM with target account list + GA4 or web analytics for engaged-session data.
### Step 1 — Get the target account list
Ask the user (multiple-choice if the client supports it): is the target account list maintained in the CRM (as an account property or list membership) or elsewhere? How many accounts are on it?
### Step 2 — Pull engagement signals
For each target account, gather available engagement signals:
- **From LinkedIn Ads:** impressions and clicks by `memberCompanyName` (company demographics; LinkedIn hides values below its privacy threshold, so small accounts may not appear)
- **From the CRM:** activities logged against the target account, meetings booked, opportunities created
- **Website visits by company:** GA4 doesn't identify companies. Use a reverse-IP tool's export (e.g. Clearbit, 6sense) or HubSpot's `HSCON` contact/company data if available
### Step 3 — Compute account-level coverage and engagement
Use `scripts/abm_engagement.py`. Outputs per account:
- Coverage (have we reached them at all)
- Engagement score (composite from impressions, clicks, site visits, activities)
- Pipeline status (opportunity / no opportunity)
- Last meaningful touchpoint
Aggregated:
- % of target accounts reached
- % of target accounts engaged
- % of target accounts in active pipeline
### Step 4 — Visualize the funnel
The question the chart needs to answer: **of our target accounts, how many are at each stage of engagement?**
A funnel chart works: target list size → reached → engaged → opportunities → closed-won. Each tier showing the absolute count and the conversion rate.
A secondary view: a list view (top 20 most-engaged target accounts that aren't yet in pipeline), since those are the highest-value follow-up targets for sales.
### Step 5 — Build the report
Use `assets/abm_engagement_report.md`. Audience: B2B marketing leader + sales counterparts running the ABM program together. ABM programs are reviewed every few weeks, so offer to publish the ad and CRM side as a live Studio dashboard (with `manage_dashboards`).
### Common variations
- **Tier the target accounts** — Tier 1 (top 50) vs Tier 2 (next 200) may need different KPIs. Higher tiers should show deeper engagement.
- **Compare ABM-touched vs untouched** — for accounts on the target list, do those that received ABM touches close at higher rates than those that didn't?
- **Persona reach within accounts** — coverage isn't just account-level; it's persona-level within accounts. The CMO and the VP of Engineering need different messaging. Pull LinkedIn engagement by `memberSeniority` or `memberJobFunction` (aggregate, not per account).
---
### Email + ads integrated funnel
**When to use:** the user runs both paid acquisition and email nurture and wants to see how they interact — does email nurture make paid clicks convert better? Does paid acquisition feed the email list usefully?
**Platforms typically involved:** ad platforms + email marketing platforms (HubSpot Marketing Email, Adobe Engage/Marketo, Mailchimp, Klaviyo, Brevo, Campaign Monitor, ActiveCampaign, Omnisend) + CRM for the conversion data.
### Step 1 — Pull the email side
> Pull the last 90 days of email campaign performance from [email platform]: campaigns sent, opens, clicks, conversions, and revenue attributed.
Also pull list growth (e.g. Mailchimp's ListGrowthHistory report). Subscriber source by channel usually comes from the CRM (HubSpot `original_traffic_source`) or GA4 sign-up events by source, not from the email platform.
### Step 2 — Pull the paid side
> Pull the last 90 days of paid acquisition data, focusing on conversions that include both "purchase" / "lead" type and "newsletter signup" / "email subscription" type.
### Step 3 — Join the views
Use `scripts/email_paid_funnel.py` (columns: `channel`, `clicks`, `spend`, `subscribed`, `converted_direct`, `converted_via_email`, `still_nurturing`). The per-channel subscriber and conversion counts usually have to be assembled from CRM or GA4 data first. The script:
- Computes paid-to-email-subscriber rate (of paid clicks, how many turned into email subscribers)
- Computes email-to-conversion rate (of nurtured subscribers, how many converted within the period)
- Identifies the channels that subscribe-then-convert at high rates (efficient acquisition through nurture) vs convert directly (efficient acquisition without nurture)
### Step 4 — Visualize the interaction
The question the chart needs to answer: **does our email nurture amplify paid acquisition, or is it a separate channel?**
A Sankey-style flow diagram is ideal here — paid channels on the left, "Subscribed", "Direct converted", or "Lost" in the middle, "Converted via email", "Converted directly", "Still nurturing" on the right. The flow widths show volume.
If a Sankey is too complex, a stacked bar per paid channel showing the split (% direct converted, % subscribed and later converted, % subscribed and still nurturing, % lost) works as a simpler alternative.
### Step 5 — Build the narrative
Use `assets/integrated_funnel_summary.md`. The interesting finding is usually one of:
- "Email amplifies acquisition — paid channels with the highest subscribe rate also have the highest eventual conversion rate via nurture"
- "Email and paid are separate channels — subscribers convert at similar rates regardless of paid source"
- "Paid acquisition is bypassing email — high direct-conversion rates mean email is mostly serving repeat business"
### Common variations
- **Per-segment email performance** — if the email platform supports segmentation, surface which segments (e.g. newsletter subscribers vs free-trial users) convert at higher rates.
- **First purchase vs repeat** — for ecommerce, separate first-purchase email influence from repeat-purchase email influence. Often very different patterns.
- **Welcome series performance specifically** — the welcome series is the highest-leverage email touchpoint. Pull its open and click rates separately.
---
## Background
Chart choices, principles and gotchas for this area: [references/demand-gen-guide.md](references/demand-gen-guide.md).
## Before you analyze
- Load saved targets, budgets and known context with `manage_business_context` (`action: get`) and judge results against them, not generic benchmarks.
- Query correctly: follow the `marketing-data-queries` skill for discovery, field IDs and platform quirks.
- Check tracking first. If platform conversions and GA4 or backend numbers disagree by more than 20%, or spend continues with zero conversions, say so before any optimization advice.
- Pull, then analyze, as separate steps. Run one heavy query at a time.
- Evidence discipline: treat changes on fewer than ~10 conversions as noise, ignore items under 1,000 impressions, don't call learning-phase campaigns failures, check for shared budgets before budget advice, and re-pull before conceding a disputed number.
- Answer shape: conclusion, business impact, next actions, then "How I got this" (one line per data pull).
- Helper scripts in `scripts/` take a CSV and print a table. Run them if you can execute code; otherwise compute the same thing directly. Templates in `assets/` shape the final deliverable.
## After the analysis
- Analysis only recommends. If the user wants to act (pause, budget shift, negatives), use the `campaign-management` skill, with explicit approval for each change.
- For a recurring or shareable result, offer once to publish it as a live Supermetrics Studio dashboard with `manage_dashboards` (static preview first, then the live upload).
Referenced files: 13 — file references are metadata, not package contents.
budget-pacing-allocation11.3 KB
View saved version →
---
name: budget-pacing-allocation
description: Check ad budget pacing and plan reallocation from live data: month-to-date spend vs budget with a month-end forecast per channel, cross-channel ROAS benchmarking, and modelled budget shifts with diminishing returns. Use for "are we on track", "where should the next euro go" and reallocation proposals.
---
# Budget pacing and allocation
## Workflows
### Budget pacing and financial forecasting
**When to use:** the user wants to know if monthly (or quarterly) ad spend is on track and what month-end totals will be. Often mid-month when there's still time to course-correct.
**Platforms typically involved:** whichever platforms have meaningful spend. For B2B usually Google Ads, LinkedIn Ads, Facebook Ads. For ecommerce, add Pinterest and TikTok.
### Step 1 — Pull month-to-date data
> Pull the daily ad spend and total conversions for the current period across [the connected ad platforms].
Daily granularity is required — the pacing script computes the run rate as the month-to-date daily average. If spend ramped mid-month, say so and project from the recent daily rate instead.
### Step 2 — Forecast period-end
Use `scripts/budget_pacing.py`. Pass in the period target budget per channel; ask the user if they haven't shared it. The script outputs period-end projections and the variance vs. target.
### Step 3 — Visualize pacing
The question the chart needs to answer: **are we on track, and where's the risk?**
The most useful visualization for this is usually a line chart per channel: cumulative spend (solid line) vs. target trajectory (dashed line, a straight line from $0 at period start to target at period end). Channels below the dashed line are underspending; above it are overspending. Shade the gap red or green based on which side of the target the channel is on.
Alternative when the user has many channels (8+): a horizontal bar chart of variance percent, sorted by absolute variance, color-coded by direction.
### Step 4 — Flag pacing issues
The script flags channels off-pace by more than ±15% (configurable). Surface the flagged channels with their projected period-end and a one-line recommendation per channel — slow down bidding, increase daily caps, redistribute budget.
### Step 5 — Output
Default delivery is the chart in chat plus a markdown summary. Pacing is checked repeatedly, so offer once to publish it as a live Studio dashboard (with `manage_dashboards`). If the user wants a spreadsheet for the planning team, use the `xlsx` skill.
### Common variations
- **"What if we hold spend flat for the rest of the period?"** — re-run the projection with the daily run rate frozen. The script supports a `--freeze-from` date.
- **Compare to last period's pacing curve, not just the target** — pull prior-period daily data and overlay both lines on the chart. Often more useful than the abstract target line.
- **Project conversions, not just spend** — the script does both. If conversion volume is the actual concern, lead with that visualization.
---
### Cross-channel ROAS benchmarking
**When to use:** the user is deciding how to allocate next period's budget across platforms and needs a defensible cross-channel comparison.
**Platforms typically involved:** Google Ads, Facebook Ads, LinkedIn Ads at minimum. For ecommerce: add TikTok, Pinterest, sometimes Amazon Ads.
### Step 1 — Pull the data
> Pull the total spend, revenue, and ROAS for the last 60 days across [the connected ad platforms].
Surface the attribution model for each platform. If the user doesn't know, name the issue explicitly in the deliverable — comparing Facebook's 7-day-click / 1-day-view ROAS to data-driven ROAS in Google is apples to oranges and a finance partner will spot it.
### Step 2 — Rank and compare
Use `scripts/roas_ranker.py`. The script ranks channels, computes the best-to-worst spread, and outputs a budget-reallocation recommendation with the diminishing-returns caveat baked in.
### Step 3 — Visualize the ranking
The question the chart needs to answer: **how different are the channels in efficiency, and what's the recommendation?**
A sorted horizontal bar chart of ROAS by channel works well as the primary visualization — bars sorted descending, the top performer highlighted, a reference line at blended ROAS so the user can see which channels are pulling weight vs. dragging.
If the user wants more dimension, a scatter of spend (x-axis) vs ROAS (y-axis), dots labeled by channel, makes the "efficient at low scale vs. efficient at scale" distinction immediately visible. Channels in the top-right (high spend, high ROAS) are the keepers; bottom-right (high spend, low ROAS) need attention.
### Step 4 — Justify the recommendation
Build from `assets/budget_reallocation_memo.md`. The memo must contain the size of the proposed shift in dollars (not just percent), and the caveat about diminishing returns on the receiving channel. Finance teams flag this almost reflexively; include it preemptively.
### Step 5 — Output
Default is the chart plus the memo inline as markdown. If the ranking will be revisited, offer once to publish it as a live Studio dashboard (with `manage_dashboards`). If the user wants a Word doc to send to finance, use the `docx` skill.
### Common variations
- **CPA instead of ROAS** — pass `--metric cpa` to the ranker. The chart logic flips (lower bars are better).
- **Compare to industry benchmarks** — Supermetrics doesn't ship benchmarks, but web search can pull recent industry data for the user's category. Overlay as a reference line on the chart.
- **Different shift percentage** — pass `--shift-pct` to the ranker (default 20%). The memo template renders whatever percentage the script was run with.
---
### Budget reallocation modeler
**When to use:** the user has current ROAS by channel and wants to model the optimal budget shift for next period, accounting for the reality that more spend on a winner doesn't produce the same ROAS at higher volume.
**Platforms typically involved:** all connected ad platforms with meaningful spend.
### Step 1 — Pull current performance
> Pull the last 30-60 days of spend and revenue (or conversions × value) by channel from [the connected ad platforms]. Include daily breakdown to surface diminishing-returns signals.
Daily granularity matters — the script needs it to detect whether ROAS holds at higher spend or compresses.
### Step 2 — Get the target spend
Ask the user (with a multiple-choice question tool if available): what's the total budget for next period? Same as current, ±10%, or a specific number?
### Step 3 — Run the optimizer
Use `scripts/budget_optimizer.py`. The script:
1. Computes current channel ROAS and spend
2. Estimates a diminishing-returns dampening factor per channel from the daily data (channels with higher spend variance and stable ROAS get dampened less; channels with ROAS that already shows compression get dampened more)
3. Models reallocation toward higher-ROAS channels, but applies the dampening so the model doesn't naively dump all budget into the single winner
4. Outputs proposed spend per channel and projected total revenue
This is a model, not a prediction. The script's output is "given these assumptions, here's the math" — not "this will happen."
### Step 4 — Visualize the recommendation
The question the chart needs to answer: **what's the proposed shift, and what's the projected impact?**
Two visualizations work well together:
- A paired bar chart per channel: current spend vs proposed spend. Sorted by absolute shift magnitude.
- A waterfall chart showing the projected revenue impact: starting from current total revenue, adding contributions from spend increases and subtractions from spend decreases, ending at projected new total.
### Step 5 — Frame the assumptions
Build from `assets/budget_reallocation_plan.md`. The plan must include:
- Specific dollar amounts per channel (current vs proposed)
- Projected revenue impact with the assumption disclosure
- The dampening logic (so finance can challenge the model intelligently)
- A 2-week checkpoint date — when to verify whether the projection is tracking
### Step 6 — Output
Default delivery: chart + plan inline as markdown. If the deliverable is going to finance for approval, use the `docx` skill.
### Common variations
- **Constrained channels** — if some channels have fixed budgets (e.g. a contracted minimum spend on a platform), pass them as `--locked` to the script. The optimizer will only reallocate the unconstrained portion.
- **Aggressive vs conservative shifts** — pass `--max-shift-pct` (default 25%) to cap how much any single channel can move. Conservative finance teams want smaller shifts.
- **Goal: total conversions, not revenue** — pass `--metric cpa`. The optimizer flips to minimizing CPA-weighted spend rather than maximizing revenue.
---
## Ad hoc analysis
The bundled scripts handle the repeatable patterns above. When the user asks something the scripts weren't designed for — "is there a time-of-day effect on this campaign?", "does ad copy length correlate with CPA?", "what's the spend distribution across ad sets — concentrated or spread?" — write fresh analysis code, run it, and build whatever visualization fits the question.
The "Choosing the right visualization" framework in the SKILL.md gives you the decision tree for which chart family fits which type of question. Apply it case by case.
---
## A note on data freshness
Platforms report with different delays. Facebook is close to real time; LinkedIn can lag up to 24 hours. Google Ads and Meta credit conversions back to the click or impression date, so the last few days keep filling in until the attribution window closes. When the user is making same-day decisions, surface this so they know what "yesterday's data" actually means.
## Background
Chart choices, principles and gotchas for this area: [references/marketing-leader-guide.md](references/marketing-leader-guide.md), [references/performance-marketer-guide.md](references/performance-marketer-guide.md).
## Before you analyze
- Load saved targets, budgets and known context with `manage_business_context` (`action: get`) and judge results against them, not generic benchmarks.
- Query correctly: follow the `marketing-data-queries` skill for discovery, field IDs and platform quirks.
- Check tracking first. If platform conversions and GA4 or backend numbers disagree by more than 20%, or spend continues with zero conversions, say so before any optimization advice.
- Pull, then analyze, as separate steps. Run one heavy query at a time.
- Evidence discipline: treat changes on fewer than ~10 conversions as noise, ignore items under 1,000 impressions, don't call learning-phase campaigns failures, check for shared budgets before budget advice, and re-pull before conceding a disputed number.
- Answer shape: conclusion, business impact, next actions, then "How I got this" (one line per data pull).
- Helper scripts in `scripts/` take a CSV and print a table. Run them if you can execute code; otherwise compute the same thing directly. Templates in `assets/` shape the final deliverable.
## After the analysis
- Analysis only recommends. If the user wants to act (pause, budget shift, negatives), use the `campaign-management` skill, with explicit approval for each change.
- For a recurring or shareable result, offer once to publish it as a live Supermetrics Studio dashboard with `manage_dashboards` (static preview first, then the live upload).
Referenced files: 9 — file references are metadata, not package contents.
campaign-management4.85 KB
View saved version →
---
name: campaign-management
description: The shared safety rules and payload shape for writing advertising campaigns through the Supermetrics MCP server — read before write, created paused, approval levels, per-field targeting updates, checking write_status. Use when the user wants to launch a campaign, change a budget or bid, pause or enable ads, edit targeting or manage creatives on ChatGPT Ads or Snapchat, when writing across several platforms at once, or for any campaign change on Google Ads, Meta Ads, Microsoft Advertising, TikTok Ads or LinkedIn Ads.
---
# Campaign management with Supermetrics
These tools spend real money. Treat every write as consequential.
Platform payload details (Google Ads, Meta, Microsoft, TikTok, LinkedIn) are in the `marketing-data-queries` skill's `references/<platform>.md` files.
## Before writing anything
1. Campaign writes must be enabled per advertising account at
[hub.supermetrics.com/write-settings](https://hub.supermetrics.com/write-settings), where the
account owner also sets an approval level: no human approval, going live, budget + going live,
or all live changes. If a write fails with a permissions error, that is usually why.
2. Read before you write. `campaign_and_resource_get` shows current state — campaigns,
ad groups, ads, keywords, audiences, budgets. Never update a campaign you have not read.
3. Check business context with `manage_business_context` (`action="get"`, plus `ds_id`
and `account_id`). Naming conventions, budget ceilings and excluded campaigns live there.
## Safety rules
- **New campaigns are always created paused.** This is enforced by the platform layer;
do not try to work around it.
- **Only set `status: "ENABLED"` when the user has explicitly approved that specific
campaign going live.** Enabling starts spend immediately.
- **Google Performance Max**: enabling the campaign is not enough — its asset groups are
paused too. Enabling those is a second, separately approved step.
- **`targeting` updates per field.** On update, omitted targeting fields are kept; each field
you send replaces that whole list, so send its complete value (all locations, all
interests), and `[]` clears it (not on Snapchat). For Google and Microsoft keywords,
`ad_groups[].add_keywords` / `remove_keywords` append and remove without touching the rest.
TikTok and LinkedIn: target existing ad groups through `ad_groups[].targeting`.
- **Confirm budgets in writing** before submitting. State the amount, the currency and
whether it is daily or lifetime.
## Creating a campaign
Use `manage_campaign` without a `campaign_id`. `budget_amount` is required. Structure:
- Campaign level: name, budget, bidding strategy, dates, campaign-level targeting.
- `ad_groups[]`: ad sets or ad groups. Omit `id` to create, include `id` to update.
- `ad_groups[].ads[]`: each needs a name and a `creative` (headlines, descriptions,
`final_urls`). Meta ads additionally require `page_id` in the ad's `platform_settings`.
Creatives accept, in order of preference: `asset_url` (a public URL), `asset_id` (already
in the ad account — find them via `campaign_and_resource_get` with
`resource_type="assets"`), or `upload_ref` from `creative_picker`. If the user has no
creative yet, open `creative_picker` to browse, upload, AI-generate or import one.
Platform quirks worth knowing before you build the payload:
- **Google Ads**: 3–15 headlines (30 chars), 2–4 descriptions (90 chars), `final_urls`
required. Performance Max images must be 1.91:1, 1:1 or 4:5 — 16:9 and 9:16 are rejected.
- **Meta**: budget sits on the campaign under CBO, on each ad set under ABO. Carousels use
`carousel_cards`, not `assets`.
- **TikTok**: video creatives must use `asset_id`; a URL will not work.
- **LinkedIn**: single image only.
## Updating
Pass `campaign_id` to update. Only the fields you send change. Campaign type and objective
are fixed at creation and cannot be changed afterwards.
Partial success is possible on multi-entity writes. Always check `write_status` and
`failures` in the response — do not assume success and do not blindly retry, which can
create duplicates.
When adding Google Ads keywords, read the response notes: a keyword that wasn't added is named
there with the reason. Report those to the user rather than assuming every keyword landed.
## After writing
Every change is logged at
[hub.supermetrics.com/campaign-history](https://hub.supermetrics.com/campaign-history).
Re-read with `campaign_and_resource_get` to confirm the final state, and tell the user
exactly what was created or changed, including which entities are paused.
## Forecasting and research
Before committing spend, `campaign_and_resource_get` also offers `resource_type` values
for planning: `forecast` (estimated performance at a given budget), `keyword_ideas` and
`keyword_volumes`, `reach_estimate`, `targeting_search`, `audiences` and `recommendations`.
Referenced files: 2 — file references are metadata, not package contents.
campaign-performance-review11.4 KB
View saved version →
---
name: campaign-performance-review
description: Review paid campaign performance from live data: week-over-week changes with causes and actions, a daily morning check (yesterday vs the 7-day average), and attribution differences between platforms. Use for weekly reviews, daily standups and "what changed" questions across Google Ads, Meta, LinkedIn, TikTok and Microsoft Ads.
---
# Campaign performance review
## Workflows
### Week-over-week campaign optimization
**When to use:** the user wants to spot efficiency decline (rising CPC, dropping conversion rate, climbing CPA) before it eats the monthly budget. Common phrasings: "compare last week to the week before," "is performance dropping," "what changed in the campaign."
**Platforms typically involved:** LinkedIn Ads, Facebook Ads, Google Ads. Confirm if the user has specific platforms in mind.
### Step 1 — Clarify the comparison (only if ambiguous)
If the user hasn't specified the time window or scope, use a multiple-choice question tool if available to clarify:
- Time window: rolling 7-day, calendar week, last 30 days, etc.
- Scope: campaign level, ad set level, or ad level
Skip if the user's phrasing already makes it obvious.
### Step 2 — Pull the data
> Pull performance data for the [campaign name] running on [platforms] for [current period] and [prior period]. Include spend, impressions, clicks, CTR, CPC, conversions, and CPA.
If the user mentioned specific KPIs (ROAS, leads, video views), include those too.
### Step 3 — Run the comparison
Use `scripts/wow_comparison.py` to compute the deltas. The script flags metrics that moved more than ±10% by default.
### Step 4 — Visualize the changes
Build an inline chart. The question the chart needs to answer: **what changed, and by how much?**
Decide the chart based on what's being compared:
- Comparing the same metrics across two time periods, one campaign at a time → horizontal bar chart of percentage changes, one bar per metric, color by business meaning (improvement vs decline)
- Comparing multiple campaigns side-by-side → grouped bars or small multiples (one mini-chart per campaign)
- Trend over many weeks rather than two snapshots → line chart with a reference line for the baseline period
Whatever you build, sort by the metric of interest (don't leave alphabetical), highlight flagged metrics with an outline or marker, and name the headline above the chart ("CTR dropped on 4 of 5 campaigns this week" — not "Performance data").
### Step 5 — Recommendations
> Generate recommendations: which specific ads to pause, where to shift the remaining budget, and what demographic segments are overperforming.
Build from `assets/optimization_doc.md`. Be specific: name ads, give dollar amounts, identify segments by their actual labels (age 25–34, mobile, iOS).
### Step 6 — Package the deliverable
Default delivery is inline markdown — fast, no friction. If the user reviews this weekly, offer once to publish it as a live Studio dashboard (with `manage_dashboards`). If the user asks for something they can share or save, the right tool depends on what they want:
- A Word doc to send around → use the `docx` skill
- A spreadsheet to sort and filter → use the `xlsx` skill
- A message to post in Slack (if a Slack connector is available) → adapt the recommendation to Slack tone (shorter, no formal greeting)
Don't overwhelm the user with options up front. Pick the sensible default and let them redirect.
### Common variations
- **By ad set instead of campaign** — re-run step 2 grouped by ad set (Facebook Ads `adset_name`, Google Ads `Adgroupname`).
- **Just one platform** — drop the cross-channel framing in step 4.
- **Compare to last month instead** — swap the time windows in step 2; the rest is identical.
- **Add lead quality from a CRM** — if a HubSpot or Salesforce connector is active, pull MQL conversion rate by source and join with the ad-platform CPA. The combined view ("$50 ad CPA but only 8% become MQLs vs another channel's $80 ad CPA with 35% MQLs") is more useful than ad-platform CPA alone. Skip if the CRM connector isn't available.
---
### Daily morning standup check
**When to use:** the user wants a quick scan of what happened yesterday across all paid channels — anomalies, wins, things to investigate. The most common "I just got to my desk, give me the headlines" workflow.
**Platforms typically involved:** all connected ad platforms (Google Ads, Facebook Ads, LinkedIn Ads, TikTok Ads, Microsoft Ads, etc.).
### Step 1 — Pull yesterday and the trailing baseline
> Pull daily spend, impressions, clicks, conversions, and conversion value for the last 8 days (yesterday plus the 7 days before) across all connected ad platforms.
The baseline matters — yesterday in isolation is meaningless. The script computes the trailing average from the daily rows; the comparison is what surfaces anomalies.
### Step 2 — Run the daily check
Use `scripts/daily_check.py`. The script computes yesterday-vs-baseline ratios per channel and flags anomalies on:
- Spend ±25% off the daily baseline (over- or under-pacing)
- CPA ±30% off (cost spike)
- Zero conversions on a channel that normally produces conversions (tracking issue suspected)
- ROAS down >20% (efficiency drop)
### Step 3 — Visualize the morning view
The question the chart needs to answer: **what's normal, what's not, and what needs my attention?**
A horizontal bar chart of percent-deviation-from-baseline per channel works as the primary visualization, with three color zones: green within ±10%, amber ±10–25%, red beyond ±25%. The user scans for red bars first.
When the user has many channels (8+), a small-multiples grid — one mini bar chart per metric (spend, CPA, ROAS) with channels on the y-axis — surfaces patterns by metric rather than by channel.
### Step 4 — Action list
Build from `assets/daily_standup_summary.md`. The summary has three sections: **what happened** (the headline), **what to act on today** (specific campaigns or ad sets, with the action), **what to watch** (early signals that aren't yet actionable).
### Step 5 — Output
Default delivery: inline markdown. For a check the user reopens every morning, offer once to publish it as a live Studio dashboard (with `manage_dashboards`). If the user wants this delivered as a recurring Slack message and a Slack connector is active, format it for Slack tone (shorter, no formal greeting) and offer to post.
### Common variations
- **Just one platform** — filter to a single platform in step 1.
- **Weekly instead of daily** — swap the time windows: pull last 7 days and compare to the prior 7-day average.
- **Custom anomaly thresholds** — pass `--spend-threshold`, `--cpa-threshold`, `--roas-threshold` to the script.
---
### Cross-channel attribution comparison
**When to use:** the user is reconciling different views of conversion data — Facebook's pixel says one thing, GA4 says another, the platform's data-driven attribution says a third. Common before any cross-channel budget decision.
**Platforms typically involved:** Google Ads, Facebook Ads, LinkedIn Ads + GA4 (mandatory for the comparison). Mobile attribution platforms (AppsFlyer, Adjust, Branch) if the user has mobile apps.
### Step 1 — Pull each view
> Pull the last 30 days of conversion counts per channel from [Google Ads, Facebook Ads, LinkedIn Ads] using each platform's default attribution. Then pull the same channels' conversions from Google Analytics 4 using GA4's default attribution.
Check each platform's attribution setting — Facebook Ads `attribution_setting` (default 7-day click / 1-day view), Google Ads `AttributionModel` (ConversionAction report; data-driven by default); GA4 reporting defaults to data-driven. If any are customized, note it explicitly.
### Step 2 — Reconcile
Use `scripts/attribution_comparator.py`. The script joins on channel name and computes the divergence between each platform's self-reported conversions and GA4's view. Flags channels where the gap exceeds ±25%.
### Step 3 — Visualize the disagreement
The question the chart needs to answer: **which channels disagree most between platform-reported and GA4-measured views, and how does this affect ROAS?**
A paired bar chart per channel works well: two bars per channel, one for platform-reported conversions and one for GA4-measured. Big gaps between the pairs are the story. Color the gaps amber when they exceed the 25% threshold.
A secondary visualization useful here: a slopegraph showing how each channel's *rank* changes between the two views. Facebook might be the #1 channel by Facebook's own attribution but the #3 channel by GA4. This rank-change view is more useful for budget decisions than absolute numbers.
### Step 4 — Frame the implication
The point of this analysis isn't to declare one view correct. It's to make the disagreement visible before a budget decision. The deliverable names what the user can and can't conclude:
- Comparing channels using each platform's own attribution → invalid (apples to oranges)
- Comparing channels using a single attribution lens (GA4 or a third-party MMM) → valid
- Estimating "true" conversion contribution → requires more than these two views; suggest incrementality testing or media mix modeling if the stakes warrant
### Step 5 — Output
Default: chart + framing inline as markdown. If the deliverable is going to a finance or leadership audience, use the `docx` skill for a clean memo.
### Common variations
- **Add mobile attribution** — if AppsFlyer, Adjust, or Branch is connected, add their view as a third comparison column.
- **Include a third-party MMM result** — if the user has results from a media mix model, layer those as a fourth view to show the spread.
- **Per-conversion-type breakdown** — if the user tracks multiple conversion events (purchases, leads, signups), run the comparison per type. Sometimes one type tracks cleanly across platforms and another doesn't.
---
## Background
Chart choices, principles and gotchas for this area: [references/performance-marketer-guide.md](references/performance-marketer-guide.md).
## Before you analyze
- Load saved targets, budgets and known context with `manage_business_context` (`action: get`) and judge results against them, not generic benchmarks.
- Query correctly: follow the `marketing-data-queries` skill for discovery, field IDs and platform quirks.
- Check tracking first. If platform conversions and GA4 or backend numbers disagree by more than 20%, or spend continues with zero conversions, say so before any optimization advice.
- Pull, then analyze, as separate steps. Run one heavy query at a time.
- Evidence discipline: treat changes on fewer than ~10 conversions as noise, ignore items under 1,000 impressions, don't call learning-phase campaigns failures, check for shared budgets before budget advice, and re-pull before conceding a disputed number.
- Answer shape: conclusion, business impact, next actions, then "How I got this" (one line per data pull).
- Helper scripts in `scripts/` take a CSV and print a table. Run them if you can execute code; otherwise compute the same thing directly. Templates in `assets/` shape the final deliverable.
## After the analysis
- Analysis only recommends. If the user wants to act (pause, budget shift, negatives), use the `campaign-management` skill, with explicit approval for each change.
- For a recurring or shareable result, offer once to publish it as a live Supermetrics Studio dashboard with `manage_dashboards` (static preview first, then the live upload).
Referenced files: 8 — file references are metadata, not package contents.
ecommerce-roas-analysis21.3 KB
View saved version →
---
name: ecommerce-roas-analysis
description: Ecommerce paid acquisition analysis from live ad and store data: blended and per-platform ROAS with day-of-week patterns, promo anomaly detection, SKU-level performance, new vs returning customer ROAS, AOV and basket composition, subscription retention cohorts and pre-promo planning. Use for Shopify and other online stores advertising on Google, Meta and TikTok.
---
# Ecommerce roas analysis
## Workflows
### Cross-platform ROAS and purchase behavior
**When to use:** the user is doing a periodic (usually monthly) review of paid acquisition efficiency across their main ecommerce platforms, and wants to surface day-of-week patterns to inform bid strategy.
**Platforms typically involved:** Google Ads and Facebook Ads at minimum. Sometimes TikTok Ads, Pinterest Ads, Snapchat Ads, Amazon Ads.
### Step 1 — Pull the data
> Pull the last 30 days of daily ad spend and purchase conversion value from [Google Ads, Facebook Ads, etc.].
Daily granularity matters — day-of-week analysis requires it. Make sure data has conversion value (revenue), not just count. If conversion value isn't populated, this workflow can't run as designed; surface that and offer the count-based version instead.
### Step 2 — Compute blended ROAS
Use `scripts/blended_roas.py`. The script computes blended ROAS daily, weekly, and by day-of-week. Mention the double-count caveat once when introducing the number, not repeatedly.
### Step 3 — Visualize the trend and patterns
Two questions worth surfacing, often as two charts:
**"Is ROAS trending up, down, or stable?"** A line chart of daily blended ROAS over the 30-day window, with a horizontal reference line at the period average. The chart makes drift visible — ROAS that's volatile day-over-day tells a different story than ROAS drifting in one direction.
**"Which days of the week perform best?"** This is the prime case for a heatmap: rows = day of week (Monday-Sunday), columns = a single column if data is daily-only, or hour columns if hourly data is available. Cell color = ROAS or conversion rate, with a diverging red-to-green scale centered on the period average. Above-average days appear green, below-average appear red, intensity shows magnitude.
If a heatmap is overkill for the user's data shape, a sorted horizontal bar chart of average ROAS by day of week works as the fallback.
### Step 4 — Budget weighting recommendation
> Build a strategic plan for adjusting weekly budget allocation to weight spending more heavily toward the days demonstrating the strongest purchase intent.
Use `assets/dow_budget_strategy.md`. The recommendation should propose a weighting (e.g. Tuesday +20%, Friday -15%) and explicitly flag what would invalidate the strategy — usually a promo period scrambling normal patterns.
### Step 5 — Output
Default delivery: charts in chat plus a markdown recommendation. For a ROAS view the team will reopen, offer once to publish it as a live Studio dashboard (with `manage_dashboards`). If the user wants a Word doc to share with the team, use the `docx` skill.
### Common variations
- **Add TikTok, Pinterest** — same workflow, expand the platform list. Watch for platforms with low spend producing noisy daily numbers.
- **Compare to prior 30-day period** — pull a second window and overlay both lines on the trend chart.
- **Break down by product category** — needs product-level data from Shopping/catalog feeds. Available if the user runs Shopping campaigns; not available if they run purely image/video.
---
### Promotional campaign anomaly detection
**When to use:** the user is running a high-stakes promo (BFCM, holiday sale, flash sale) and wants to catch cost-per-purchase anomalies before they burn the day's budget.
**Platforms typically involved:** Facebook Ads most often (BFCM spend concentrates there for many DTC brands). Google Ads where applicable.
### Step 1 — Pull yesterday's promo data
> Pull yesterday's data for the [promo campaign filter — e.g. campaigns containing "BFCM" or "Black Friday"] on Facebook Ads. Include cost, impressions, and total purchases per ad set.
Use the user's actual filter convention. Confirm if unclear. Ad-set granularity matters — a campaign-level 3x spike might be driven by one bad ad set, not the whole campaign.
### Step 2 — Pull the baseline
Get the prior 6 days of data for the same campaigns. The script computes the rolling-average baseline.
### Step 3 — Flag the anomaly
Use `scripts/anomaly_detector.py`. Default threshold: yesterday's cost-per-purchase >3x the trailing 6-day average. The script identifies which ad sets are responsible and flags candidate causes (tracking failure vs real performance issue).
If no anomaly is detected, surface that clearly. "No anomaly, performance within expected range" is a valid and useful answer.
### Step 4 — Visualize the spike (if one exists)
The question the chart needs to answer: **which ad sets are anomalous, by how much, and what's the likely cause?**
A line chart showing the trailing 7 days of cost-per-purchase per anomalous ad set works well — most days sit in a horizontal band, then yesterday's value spikes upward. The spike day gets highlighted in amber. A reference line at the baseline average makes the deviation visible.
When multiple ad sets are anomalous, a sorted horizontal bar chart of yesterday's CPP-to-baseline ratio surfaces which are the worst — the user fixes the biggest bleeders first.
For non-anomalous ad sets, no chart is needed — just the headline.
### Step 5 — Verify before alerting
Before drafting any alert email: verify the spike is real, not a tracking issue. The most common causes of an apparent 3x spike are pixel failures, renamed events, or deduplication issues — not real performance failures. The script's candidate-cause column points at likely explanations; investigation is on the user.
### Step 6 — Draft the urgent alert
Use `assets/media_buyer_alert_email.md`. The email needs to be short, specific (named ad sets), and recommend a concrete action.
Default delivery: markdown inline so the user reviews before sending. If Gmail is connected, offer to save as a draft. If the user prefers Slack and a Slack connector is available, post the alert to the relevant channel instead — often faster during a promo when the media buying team is fielding many messages per hour.
### Common variations
- **Baseline isn't 6 days, it's same-promo-week-last-year** — the script only supports a trailing baseline (`--baseline-days`); compute ratios against last year's promo week ad hoc.
- **Monitor ROAS, not cost per purchase** — same workflow, swap the metric. Pass `--metric roas`.
- **Hourly granularity, not daily** — supported on Facebook and Google but noise floor is high. Use only for high-spend ($50k+/day) campaigns.
---
### Product / SKU-level performance
**When to use:** the user wants to know which specific products are driving paid-acquisition revenue, not just which campaigns. Used to inform creative direction, inventory planning, and bid strategy.
**Platforms typically involved:** an ecommerce backend (Shopify, BigCommerce, WooCommerce, Adobe Commerce, Squarespace, Wix, PrestaShop, Centra, Ecwid, Amazon Seller Central, TikTok Shop) + ad platforms with product-level reporting (Google Shopping, Meta Catalog ads, TikTok Shop ads).
### Step 1 — Pull product-level sales
> Pull the last 30-60 days of product-level sales from [Shopify / BigCommerce / WooCommerce]: SKU, product name, units sold, revenue, gross margin if available.
### Step 2 — Pull ad-driven attribution
> Pull product-level performance from [Google Shopping / Meta product catalog / TikTok Shop ads]: SKU, impressions, clicks, spend, attributed purchases, attributed revenue.
### Step 3 — Join and rank
Use `scripts/sku_performance.py`. The script:
- Joins ad-driven attribution with total sales
- Computes the % of each SKU's revenue that came from paid ads
- Surfaces high-margin SKUs underspending on ads (opportunity)
- Surfaces low-margin SKUs overspending on ads (cut candidates)
- Flags SKUs with high return rates if return data is available
### Step 4 — Visualize the SKU portfolio
The question the chart needs to answer: **which products deserve more ad investment, which deserve less?**
A scatter plot works well: x-axis = total revenue, y-axis = ad ROAS for that SKU. Dots colored by margin tier (high/medium/low margin), sized by units sold. The user sees the high-revenue, high-ROAS, high-margin winners immediately.
A secondary view: top 20 SKUs by ad-attributed revenue, with bars colored by margin tier. Surfaces concentration — often 5-10 SKUs drive 80% of ad revenue.
### Step 5 — Build the report
Use `assets/sku_performance_report.md`. The doc should recommend specific products for:
- **Scale up** — high ROAS, high margin, inventory available
- **Hold** — performing as expected
- **Cut from ads** — low ROAS or low margin, ad spend not earning
- **Add to ads** — strong organic sales, not yet promoted, high margin
### Common variations
- **Add inventory levels** — if an inventory feed is available, surface SKUs with low stock to avoid promoting out-of-stock products.
- **By collection or category** — instead of SKU-by-SKU, group into categories for higher-level decisions.
- **Seasonal SKUs** — for seasonal products, surface the year-over-year same-period comparison.
---
### New vs returning customer ROAS by channel
**When to use:** the user wants to know whether their ad spend is acquiring new customers or just re-converting existing ones. Different channels often have very different splits.
**Platforms typically involved:** ad platforms + ecommerce backend with customer-type segmentation (Shopify, BigCommerce, etc.) + GA4 if available (for the customer-type dimension on conversions).
### Step 1 — Pull channel-level spend
> Pull the last 30-60 days of spend by channel from [ad platforms].
### Step 2 — Pull purchases segmented by customer type
> Pull purchases segmented into "new customer" (first-time buyer) and "returning customer" (repeat) from [Shopify / GA4]. Break out by channel.
Prefer the store's own flag (Shopify `order_is_returning_customer`, with `order_utm_source` for channel) — it is purchase-based. GA4's `newVsReturning` counts prior sessions, not prior purchases, so it isn't a buyer split; GA4's first-time purchaser metrics are closer.
### Step 3 — Compute split ROAS
Use `scripts/customer_type_roas.py`. Outputs per channel:
- Total ROAS
- New-customer ROAS (revenue from new buyers / spend)
- Returning-customer ROAS
- % of revenue from new customers
- Cost per new customer (CAC)
### Step 4 — Visualize the split
The question the chart needs to answer: **which channels acquire new customers, and which mostly serve repeat buyers?**
A stacked bar chart per channel works well: each bar shows the channel's total revenue, split into new and returning customer revenue. Surfaces channels that are mostly retargeting vs mostly acquisition.
A secondary view: paired bars per channel showing new-customer-CAC and returning-customer-CAC side by side. Some channels acquire new customers at $X but the channel's apparent ROAS is inflated by returning-customer revenue.
### Step 5 — Build the brief
Use `assets/customer_acquisition_brief.md`. The interesting finding usually centers on which channels are real acquisition vs which are retargeting in disguise.
### Common variations
- **Compare to organic** — many ecommerce businesses get more new customers via organic than paid. Surface organic for context.
- **Subscription / repeat purchase business** — the workflow becomes "first-purchase ROAS" vs "subsequent-purchase ROAS" where channels driving subsequent purchases are particularly valuable.
- **By acquisition cohort** — track new customers acquired this month by their first-purchase channel; see how they behave over the next 90 days.
---
### AOV and basket composition
**When to use:** the user wants to understand average order value (AOV) and items-per-order patterns, often as a precursor to upsell, cross-sell, or free-shipping-threshold decisions.
**Platforms typically involved:** ecommerce backend (Shopify, BigCommerce, WooCommerce, etc.) + ad platforms for channel-level breakdown.
### Step 1 — Pull order-level data
> Pull the last 30-90 days of order-level data from [ecommerce backend]: order value, item count, products, channel attribution if available.
If channel attribution isn't on the order data, join with ad-platform purchase data by date/customer.
### Step 2 — Compute AOV and basket patterns
Use `scripts/aov_analyzer.py`. Outputs:
- AOV by channel
- Items per order distribution
- AOV percentiles (P25, P50, P75, P90) to understand the distribution shape
- Free-shipping-threshold proximity (% of orders just under common thresholds like $50, $75, $100)
### Step 3 — Visualize the patterns
The question the chart needs to answer: **what does the basket look like, and where's the upsell opportunity?**
A box plot of AOV by channel surfaces both central tendency and distribution. A complementary histogram of order values with vertical reference lines at common free-shipping thresholds shows the upsell opportunity.
A bar chart of items-per-order distribution (1, 2, 3, 4+ items) by channel shows which channels drive single-item vs basket-building purchases.
### Step 4 — Build the summary
Use `assets/aov_summary.md`. The most-useful section is usually the free-shipping-threshold analysis — if a meaningful % of orders are just under the threshold, raising or lowering it has predictable effects.
### Common variations
- **Pre/post threshold change** — if the user has changed their free-shipping threshold recently, compare AOV distributions pre/post.
- **Promotional vs non-promotional periods** — AOV typically rises during promos (people buy more to hit discount thresholds). Surface the contrast.
- **First-time-buyer AOV vs repeat-buyer AOV** — repeat buyers usually have higher AOV. The size of the gap tells you how much retention is worth.
---
### Subscription / retention cohort analysis
**When to use:** the user runs a subscription business (Recharge on Shopify, native subscription products) or a repeat-purchase ecommerce business and wants to track retention by acquisition cohort.
**Platforms typically involved:** subscription platform (Recharge), payments (Stripe), or ecommerce backend with subscription/repeat-purchase data + ad platforms for cohort acquisition cost.
### Step 1 — Pull cohort data
> Pull customers grouped by acquisition month for the last 12 months. For each cohort, pull monthly revenue or active subscriber count for each month since acquisition.
### Step 2 — Pull acquisition costs
> Pull marketing spend per month over the same period. If channel-level CAC is available, pull that too.
### Step 3 — Compute retention metrics
Use `scripts/subscription_cohorts.py`. Outputs:
- Cohort retention curve (% of cohort still active by month-since-acquisition)
- Cohort cumulative revenue per customer
- Time-to-payback (months for cumulative revenue per customer to exceed CAC)
- Cohort LTV at 3/6/12/24 month horizons
### Step 4 — Visualize the cohort behavior
The question the chart needs to answer: **how does customer behavior change with cohort age, and are recent cohorts behaving like older ones?**
Two complementary visualizations:
- **Retention curves**: line chart with one line per cohort. X-axis = months since acquisition, Y-axis = % of cohort still active or % of cohort generating revenue. Steeper curves = worse retention; flatter curves = better retention. Overlapping curves means recent cohorts behave like older ones; diverging curves (with newer cohorts lower) is a warning sign.
- **Cumulative cohort revenue per customer**: line chart with one line per cohort showing $ revenue per customer over time. Reach to CAC level marks the payback moment.
### Step 5 — Build the report
Use `assets/retention_cohort_report.md`. The audience is typically the marketing leader and possibly the CFO — retention numbers feed unit economics decisions.
### Common variations
- **By acquisition channel** — different channels often produce cohorts with very different retention. The cheapest CAC channel often has the worst retention.
- **By acquisition campaign or promo** — heavy promo cohorts (50% off first month) typically have worse retention than full-price cohorts. Worth surfacing.
- **By product mix on first purchase** — for ecommerce, the first product purchased often predicts retention. Subscription-product-first vs one-time-product-first cohorts behave very differently.
---
### Pre-promo planning model
**When to use:** the user is planning a high-stakes promotional period (BFCM, summer sale, etc.) and needs to set budget, AOV, and ROAS targets based on historical performance.
**Platforms typically involved:** ad platforms + ecommerce backend, both showing prior promo periods.
### Step 1 — Pull prior promo data
> Pull spend, purchases, revenue, AOV, and ROAS from the equivalent promo period last year (and the year before if available) across all relevant channels.
Use the actual promo dates, not "last November" — promos have specific date windows that matter.
### Step 2 — Pull baseline data
> Pull the same metrics from the trailing 30 days before the prior promo started. Used to compute the promo lift over baseline.
### Step 3 — Model the upcoming promo
Use `scripts/promo_planner.py`. Inputs:
- Last year's promo numbers (auto-derived from the pulled data)
- Year-over-year growth assumption (user provides)
- Planned budget for the upcoming promo
Outputs:
- Projected purchases, revenue, AOV, ROAS for the upcoming promo
- Per-channel projected spend and outcomes
- Stretch and conservative scenarios
### Step 4 — Visualize the plan
A bar chart comparing prior year actuals vs proposed plan for each metric (spend, purchases, revenue, AOV, ROAS) makes the proposal scannable.
A second chart projects daily spend over the promo period — useful for media buyers planning the pacing.
### Step 5 — Build the plan
Use `assets/promo_plan_doc.md`. The plan must include:
- Targets per metric (with stretch and conservative bands)
- Per-channel allocation
- Daily pacing
- Anomaly thresholds (when to alert the team mid-promo)
- Post-promo measurement plan
### Common variations
- **First-time-running-this-promo** — no prior data. Use industry benchmarks from web search; surface the higher uncertainty explicitly.
- **Different mix this year** — if the channel mix differs from prior year (e.g. adding TikTok), the prior-year model needs adjustment. Surface what's being assumed.
- **Multi-week promo** — model per-week pacing if the promo runs more than 3-4 days. Customer behavior often differs early-promo vs late-promo.
---
## Ad hoc analysis
For one-off questions outside these seven workflows ("what's the AOV distribution across our top SKUs in this campaign?", "is there an LTV difference between Facebook and Google traffic?", "did this discount code drive incremental purchases or cannibalize existing demand?"), write fresh analysis code. The "Choosing the right visualization" framework in the SKILL.md tells you which chart family fits.
---
## A note on promo-period analysis
Normal-period and promo-period analysis behave differently:
- **Conversion rates spike during promos** because intent is high. Day-of-week patterns from non-promo periods don't predict promo behavior.
- **CPMs spike during promos** because everyone is bidding harder. Cost-per-purchase increases during BFCM aren't always efficiency loss — it might be competitive pressure.
- **Pixels and tracking break more during promos** because traffic volume is higher and edge cases get exposed. Before alerting on an anomaly, verify tracking is healthy.
When the user is doing post-promo analysis, frame as "vs. last year's same period" rather than "vs. last month" — same-period comparison removes the seasonal confound.
## Background
Chart choices, principles and gotchas for this area: [references/ecommerce-marketer-guide.md](references/ecommerce-marketer-guide.md).
## Before you analyze
- Load saved targets, budgets and known context with `manage_business_context` (`action: get`) and judge results against them, not generic benchmarks.
- Query correctly: follow the `marketing-data-queries` skill for discovery, field IDs and platform quirks.
- Check tracking first. If platform conversions and GA4 or backend numbers disagree by more than 20%, or spend continues with zero conversions, say so before any optimization advice.
- Pull, then analyze, as separate steps. Run one heavy query at a time.
- Evidence discipline: treat changes on fewer than ~10 conversions as noise, ignore items under 1,000 impressions, don't call learning-phase campaigns failures, check for shared budgets before budget advice, and re-pull before conceding a disputed number.
- Answer shape: conclusion, business impact, next actions, then "How I got this" (one line per data pull).
- Helper scripts in `scripts/` take a CSV and print a table. Run them if you can execute code; otherwise compute the same thing directly. Templates in `assets/` shape the final deliverable.
## After the analysis
- Analysis only recommends. If the user wants to act (pause, budget shift, negatives), use the `campaign-management` skill, with explicit approval for each change.
- For a recurring or shareable result, offer once to publish it as a live Supermetrics Studio dashboard with `manage_dashboards` (static preview first, then the live upload).
Referenced files: 17 — file references are metadata, not package contents.
event-and-webinar-roi27 KB
View saved version →
---
name: event-and-webinar-roi
description: Field and event marketing analysis from live data: pre-event channel ROI, post-event geo-lift, event portfolio, event-driven pipeline, account engagement, webinar funnels and partner event ROI. Use for conferences, field events, webinars and gated content.
---
# Event and webinar roi
## Workflows
### Pre-event channel ROI
**When to use:** the user is days or weeks from an event, wants to know where to put the remaining promotion budget, and needs to update the regional team on the plan.
**Platforms typically involved:** LinkedIn Ads and Google Ads most commonly. Facebook Ads occasionally.
### Step 1 — Pull the data
> Pull the last 30 days of performance data for campaigns containing [user's event naming convention — Event_, Webinar_, etc.] across [LinkedIn Ads, Google Ads, etc.].
Ask the user about the naming convention if unclear. Look for spend, clicks, and registrations (sometimes called conversions depending on platform setup).
If ad-platform registration numbers diverge significantly from the event platform (Zoom, Eventbrite, ON24 — not Supermetrics sources, so ask for the count or an export), flag the discrepancy before proceeding — the comparison is misleading otherwise.
### Step 2 — Compare cost per registration
Use `scripts/registration_cost_compare.py` (columns: `channel`, `spend`, `clicks`, `registrations`). The script warns when conclusions are based on fewer than 30 registrations per channel — the threshold below which CPR differences are likely noise.
### Step 3 — Visualize the comparison
The question the chart needs to answer: **which channel is generating registrations more efficiently, and how confident are we?**
A sorted horizontal bar chart of cost-per-registration works as the primary visualization, with bars sorted ascending (cheapest first). When sample sizes are small for one or more channels, distinguish those bars visually — lower opacity, a hatched pattern, or a "low confidence" badge next to the label — so the user doesn't over-trust low-N comparisons.
For richer context, a paired bar chart per channel showing CPR + registration rate side-by-side surfaces the trade-offs (sometimes the cheaper channel also has lower-quality engagement).
If the user is tracking pacing toward a registration target, a line chart of cumulative registrations vs target trajectory makes the gap visible.
### Step 4 — Recommend budget shift
The recommendation should be concrete: dollar amount, source channel, destination channel, expected lift in registrations. If sample size is low, recommend a smaller hedged shift (e.g. 15% rather than 50%) and explain why.
### Step 5 — Update the regional team
Use `assets/regional_team_update.md`. The message is short — Slack-length even if delivered as email.
If a Slack connector is active, the update typically goes there directly to the regional team's channel. If not, default to inline markdown the user can copy. If the user wants to act on the budget shift, the `campaign-management` skill can apply it with their approval.
### Common variations
- **"What if we extend the campaign?"** — model expected additional registrations at current CPR. The script accepts a `--projected-days` flag.
- **Paid vs organic separately** — if the user has tagging that separates them, run the comparison separately rather than averaging.
- **Add cost per attendee** — needs post-event attendance data, which doesn't exist yet pre-event. If the user has historical attendance rates by channel, model expected attendees but state the assumption.
---
### Post-event geo-targeted follow-up
**When to use:** the user just ran an in-person event in a specific region and wants to quantify whether it drove digital engagement lift locally.
**Platforms typically involved:** Facebook Ads, LinkedIn Ads at minimum. Google Ads if search campaigns ran. Campaigns need geo-targeting configured.
### Step 1 — Pull the regional data
> Pull the performance data from the last 14 days for the [Facebook Ads, LinkedIn Ads] campaigns geographically targeted to [region].
Be specific about the region's definition — city, metro, state. Pull the regional split with each platform's geo dimension (Facebook Ads `Region`, Google Ads location reports, LinkedIn Ads `memberRegion`). LinkedIn's member region is where engaged members are, not the targeting, and is hidden below privacy thresholds. To read a campaign's targeting settings, use `campaign_and_resource_get` (read-only).
### Step 2 — Compare to national baseline
Use `scripts/geo_lift_analyzer.py --target-region "<region>"` on a CSV with one row per region (`region`, `clicks`, `impressions`, `conversions`, `spend`) covering all regions, not just the target. The script normalizes regional metrics against a national baseline that excludes the target region (so the comparison isn't diluted by including the target in the baseline).
### Step 3 — Visualize the lift
The question the chart needs to answer: **did the event drive measurable digital lift in the region, and how big is the effect?**
A paired bar chart per metric (CTR, conversion rate, CPC) with two bars per group — target region vs rest-of-country — makes the lift immediately visible. Color the target region in indigo and the baseline in a lighter shade so they read as two views of the same data.
When the user wants to see the magnitude of lift as a single number, a horizontal bar chart of percent-lift per metric (CTR +44%, conversion rate +24%, CPC -41%) is faster to read. Color by direction of lift relative to what's good (CTR up is green, CPC down is green).
### Step 4 — Verdict
The script returns one of three verdicts: measurable lift / no detectable lift / insufficient data. Use this verdict explicitly in the deliverable — don't soften it. Field marketing measurement is more credible when the analyst names "we can't tell" rather than overclaiming.
### Step 5 — Build the post-event summary
Use `assets/post_event_lift_summary.md`. The doc should include the verdict, the data, what's confounded (paid promotion that ran in the region, simultaneous events), and what to do differently next time for cleaner measurement.
Default delivery: build as a Word doc with the `docx` skill if the user wants it as a leadership readout. Otherwise inline markdown.
### Common variations
- **Compare to same region last quarter, not to national** — different baseline, same workflow shape. Often a stronger test of "did the event do something."
- **Include earned media metrics** — usually outside Supermetrics. The user may have a PR or social listening tool with this data.
- **Project the pipeline impact** — risky. Pipeline attribution to a single event is fragile. If the user wants this, frame as a model with stated assumptions, not a measurement.
---
### Multi-event portfolio analysis
**When to use:** the user has run 10-30 events over a quarter (or year) and wants to identify which event types and formats produce the best ROI. Used for next-period event planning and budget allocation.
**Platforms typically involved:** ad platforms (for promotion costs) + event platform / form platform for registration data + CRM for downstream pipeline (if available).
### Step 1 — Pull the event roster
> Pull the list of events held in [period]: event name, type (in-person / webinar / virtual conference / dinner / workshop), location, date, total spend (promotion + venue + production).
This roster usually lives in a spreadsheet or project tool, so ask the user for it (if it's in Google Sheets, Supermetrics can read it with the Google Sheets connector). Promotion spend per event can come from the ad platforms by campaign name.
### Step 2 — Pull registrations and attendance
> For each event, get registrations and attendance counts (from the event platform export or the CRM's campaign records). From the CRM (if connected), pull MQLs created within 30 days of the event from attendees.
### Step 3 — Compute composite ROI
Use `scripts/event_portfolio.py` (columns: `event_name`, `event_type`, `date`, `total_cost`, `registrations`, `attendees`, optional `location`, `mqls_within_30d`, `pipeline_value`). The script computes per event:
- Cost per registration
- Cost per attendee (CPA)
- Attendance rate
- MQL conversion rate from attendees (if CRM data available)
- Cost per MQL via the event
- Composite score (cost per attendee and MQL rate, normalized within event type)
### Step 4 — Visualize the portfolio
The question the chart needs to answer: **which event types and locations consistently produce the best outcomes?**
A scatter plot works: x-axis = cost per attendee, y-axis = MQL conversion rate (or pipeline value if available). Dots colored by event type, sized by total attendees. The user sees the best-ROI quadrant immediately.
A secondary view: bar chart of average composite ROI by event type, sorted descending. Surfaces which formats deserve more investment.
### Step 5 — Build the portfolio review
Use `assets/event_portfolio_review.md` (offer a live Studio dashboard via the `manage_dashboards` for the promotion-spend side if this is reviewed every quarter). The doc should split into:
- **Best performers** (continue running)
- **Underperformers** (need improvement or sunset)
- **Experiments worth repeating** (one-off events with promising signals)
- **Recommended next-period mix** (specific event types and counts)
### Common variations
- **By region** — break out the portfolio by region to see whether the best-performing event types differ geographically.
- **By persona** — if attendee data includes job titles, cluster by target persona and see which event types attract which personas.
- **Sponsorship vs hosted** — separately analyze events the user hosted vs sponsored. The economics are different.
---
### Event-driven pipeline tracking
**When to use:** the user has run an event and wants to track the pipeline created by attendees over 30, 60, and 90 day windows. The deliverable usually goes to sales leadership to justify event investment.
**Platforms typically involved:** event platform for attendee list + CRM (HubSpot, Salesforce, Pipedrive) for pipeline tracking.
### Step 1 — Get the attendee list
> Get the attendee list for [event] (the user's event-platform export) including email addresses, company names, and job titles.
### Step 2 — Match attendees to CRM contacts
> For each attendee, find their CRM contact record. Pull: any opportunities created within 30/60/90 days of the event date, opportunity stage, opportunity amount.
Matching is usually by email but may need company-name fuzzy matching for attendees who used personal emails. Supermetrics returns CRM report data (e.g. HubSpot `HSCON` contacts with email, Salesforce Opportunities and Campaigns reports), so pull the contact and opportunity tables and match them to the attendee list yourself. If the event is a Salesforce campaign, its responses, opportunities and won opportunities are available directly on the Campaigns report.
### Step 3 — Track pipeline progression
Use `scripts/event_pipeline_tracker.py --event-date YYYY-MM-DD --event-cost N` (columns: `attendee_email`, `matched_in_crm`, `opp_created_date`, `opp_amount`, `opp_stage`, optional `attendee_company`). The script computes:
- Total attendees
- Attendees matched to CRM contacts
- New opportunities created (in each 30/60/90 day window)
- Total pipeline value per window
- Closed-won deals (if any have closed)
- Pipeline ROAS (pipeline value / event cost)
### Step 4 — Visualize the conversion timing
The question the chart needs to answer: **how does pipeline from this event accumulate over time?**
A cumulative line chart works well: x-axis = days since event, y-axis = cumulative pipeline value. Mark the 30/60/90 day milestones. Shows whether the event produced fast-moving pipeline or slow-developing pipeline.
A secondary view: funnel chart from attendees → matched → opp created → closed-won, with the conversion rate at each step.
### Step 5 — Build the report
Use `assets/event_pipeline_report.md`. Audience: VP of Sales or CRO + the marketing leader who approved the event budget.
### Common variations
- **Compare events** — same workflow, multiple events. Surface which events drove the most pipeline relative to investment.
- **Include net-new contacts** — for accounts not previously in CRM that came in via the event. These are pure event acquisition; existing accounts that attended are influence vs acquisition.
- **Per-persona pipeline** — if event attendees include multiple personas (e.g. CMO, VP Marketing, Director), break out pipeline by attending persona to see which roles convert.
---
### Account engagement scoring
**When to use:** the user runs B2B events where the goal is to deepen relationships with target accounts (vs raw lead capture). Specifically for ABM-aligned events.
**Platforms typically involved:** event platform for attendee data + CRM for target account list + LinkedIn Ads (if ABM ads were running) + GA4 for site behavior (if company-level identification is available).
### Step 1 — Define the target account list
Ask the user: which accounts are the priority for this event? Usually a tier-1 ABM list of 50-200 accounts.
### Step 2 — Compile engagement signals per account
For each target account, gather signals from the period spanning the event (e.g. 2 weeks before through 2 weeks after):
- Number of attendees from the account
- Seniority of attendees (CEO/VP/Director/IC)
- Pre-event LinkedIn ad impressions and clicks by `memberCompanyName` (where LinkedIn's privacy threshold allows)
- Post-event website visits (needs a company-identification tool; GA4 doesn't identify companies)
- Sales activities logged (meetings booked, emails exchanged)
### Step 3 — Score engagement per account
Use `scripts/account_engagement.py` (columns: `account_name`, `attendees_from_account`, `max_seniority`, `pre_event_ad_impressions`, `pre_event_ad_clicks`, `post_event_web_sessions`, `meetings_booked`, `in_pipeline`, optional `tier`, `opportunity_amount`). The script computes per account:
- Engagement score (0-100, composite of all signals)
- Tier classification (engaged / warming / aware / cold)
- Whether the account is in active pipeline
- Last meaningful touchpoint
### Step 4 — Visualize the program-level outcome
The question the chart needs to answer: **how many target accounts did the event meaningfully engage, and which are ready for sales follow-up?**
A funnel chart works: target accounts → reached pre-event → attended → engaged post-event → in active pipeline. Each tier showing conversion rate.
A secondary view: the top 20 most-engaged accounts not yet in pipeline. This is the hand-off list for sales.
### Step 5 — Build the brief
Use `assets/account_engagement_brief.md`. Audience: B2B marketing + sales counterparts.
### Common variations
- **Tier-specific KPIs** — Tier 1 accounts may need a different success bar than Tier 2 (e.g. attendance + meeting booked for Tier 1; attendance alone for Tier 2).
- **Compare to non-target attendees** — separate engagement metrics for target-account attendees vs general attendees. Often the program optimizes for general count when the actual goal is target account depth.
- **Per-persona engagement** — track whether multiple personas from the same account attended (the C-suite + VP combination is often a stronger signal than two ICs).
---
### Webinar funnel deep dive
**When to use:** the user runs webinars regularly and wants a detailed performance review — not just registration cost but the full funnel through attendance, engagement, and downstream behavior.
**Platforms typically involved:** webinar platform (Zoom, ON24, Webex, GoToWebinar — not Supermetrics sources, so the user provides the attendance data) + form platform (HubSpot Marketing Forms or similar) + CRM for downstream tracking + ad platforms for promotion attribution.
### Step 1 — Pull the full funnel
> For [webinar], gather: total registrations by source, attendees (live and on-demand), average watch time, poll/Q&A participation rate, post-webinar email engagement, and MQLs created within 30 days of attendance.
### Step 2 — Cohort by registration source
Use `scripts/webinar_funnel.py` (columns: `source`, `spend`, `registrations`, `attended_live`, `attended_on_demand`, `high_engagement`, `mqls_within_30d`). The script breaks out funnel performance by registration source (LinkedIn Ads, Google Ads, Email, Organic, Partner referral, etc.):
- Registration count
- Attendance rate (live)
- On-demand attendance rate (post-event watch)
- Engagement rate (Q&A participation, poll responses)
- MQL conversion rate
- Cost per MQL via webinar (where promotion cost is allocable)
### Step 3 — Visualize where each source drops off
The question the chart needs to answer: **which registration sources produce the highest-quality webinar audience, not just the cheapest registrations?**
A horizontal grouped bar chart per source, with bars for each funnel stage (register, attend live, attend total, engage, MQL), colored consistently. Surfaces patterns like "LinkedIn Ads registers fewer but attends at 2x the rate" or "Email registers most but engages least."
### Step 4 — Build the summary
Use `assets/webinar_funnel_summary.md`. For a recurring webinar program, offer to publish the promotion and registration side as a live Studio dashboard (with `manage_dashboards`). The most-useful content is the source-level cost-per-MQL comparison and the engagement-rate breakdown.
### Common variations
- **Live vs on-demand split** — many webinars deliver more value on-demand than live. Surface the on-demand performance separately; it's often the dominant funnel.
- **Speaker analysis** — if the user runs multiple webinars with different speakers, compare attendance and engagement by speaker. Some speakers consistently drive better outcomes.
- **Topic clustering** — if the user has run 5+ webinars in a quarter, cluster by topic to see which themes drive engagement.
---
### Partner / co-marketing event ROI
**When to use:** the user runs events with sponsorship partners or co-marketing partners (e.g. a joint webinar with a complementary vendor, a sponsored conference appearance). The ROI math is different because costs and audience reach are shared.
**Platforms typically involved:** ad platforms + event platform / form platform + CRM for pipeline. Partner-shared metrics may need to come from the partner directly.
### Step 1 — Define the shared and unshared costs
Ask the user:
- Sponsorship fee or co-marketing commitment ($)
- The user's own promotion spend on top of the sponsorship
- Estimated value of the partner's promotion reach (use only if partner shared the number)
- The user's production/staff costs
### Step 2 — Pull attribution data
> Pull registrations and form fills tagged with the [partner event] campaign source. From the CRM, pull MQLs and opportunities created from these contacts.
### Step 3 — Compute partner-specific ROI
Use `scripts/partner_event_roi.py costs.csv` (rows of `cost_category` = sponsorship_fee / user_promotion / user_production / partner_inkind, and `amount`) with `--user-registrations`, `--user-mqls`, `--user-pipeline`. The script computes:
- Total cost (the user's investment; partner in-kind is shown separately)
- Cost per registration and cost per MQL
- Pipeline ROAS
Net-new contacts (not previously in CRM) and 60-day pipeline have to be counted from CRM data first; the script takes the totals.
If the user provided partner-side numbers (`--partner-registrations`, `--partner-mqls`, `--partner-pipeline`), the script also prints a "blended" view next to the "user-only" one.
### Step 4 — Frame the partner-specific lens
A pure "registrations" view undersells partner events because much of the value is being in front of the partner's audience for brand awareness — hard to measure but real. The visualization should show both:
- The measurable outcomes (registrations, MQLs, pipeline) as bar charts
- The strategic outcomes (audience reach, partner relationship, content reuse) as qualitative notes
The chart on its own won't answer "was the partnership worth it" — the doc has to frame it.
### Step 5 — Build the recap
Use `assets/partner_event_recap.md`. Often shared with the partner as a joint debrief; tone should be collaborative.
### Common variations
- **Sponsored conference** — different shape than joint webinars. Booth traffic, badge scans, on-site meetings booked all matter.
- **Renewal decision** — if the user is deciding whether to renew a sponsorship, the recap doc is the input. Add an explicit renew/decline section with the decision criteria.
- **New partner test** — if this was a first-time partnership, surface what worked operationally (lead handoff, content creation, audience access) in addition to numbers. Often the operational fit matters more than the first-event numbers.
---
## Ad hoc analysis
For one-off questions outside these seven workflows ("which job titles registered through which channel?", "what's the no-show rate by referring source?", "did social shares correlate with registration spikes?"), write fresh analysis code. The "Choosing the right visualization" framework in the SKILL.md tells you which chart family fits.
---
## A note on the field marketing audience
Field marketers communicate sideways — to regional sales reps, local partners, event ops — more than upward to leadership. The tone is faster and less formal than what marketing leadership produces. Match that tone: short, specific, no preamble. A "regional team update" is closer to a Slack message than a memo, even when delivered as email.
### Webinar / gated content funnel analysis
**When to use:** the user runs webinars, ebooks, whitepapers, or other gated content as part of demand gen, and wants to measure the full funnel from paid promotion through registration, attendance/download, and downstream MQL behavior.
**Platforms typically involved:** ad platforms + HubSpot Marketing Forms (views and submissions per form) or GA4 form key events + CRM for downstream tracking (HubSpot `HSCON` contact `first_conversion`/`recent_conversion` and lifecycle dates, or the Salesforce Campaigns report: responses, leads and opportunities per campaign) + email platform. Webinar attendance (Zoom, ON24, etc.) is not a Supermetrics source; ask the user for an export.
### Step 1 — Pull paid promotion data
> Pull the last 30-60 days of paid ad performance for campaigns promoting the specific content asset (webinar, ebook, etc.). Include spend, clicks, and platform-reported conversions.
### Step 2 — Pull registrations
> Pull form submissions for [content asset] from [form platform / CRM], including source for each registration (e.g. HubSpot contact `original_traffic_source`).
### Step 3 — Pull downstream behavior
For each registration, pull from the CRM:
- Did they attend / download?
- Did they become an MQL within 30 days?
- Did they enter pipeline within 60 days?
### Step 4 — Compute the funnel per channel
Use `scripts/gated_content_funnel.py` (columns: `channel`, `spend`, `clicks`, `registrations`, `attended_or_downloaded`, `mqls_within_30_days`, optional `opportunities_within_60_days`). Outputs per paid channel:
- Spend
- Clicks
- Registrations (and registration rate from clicks)
- Attendees/downloaders (and rate from registrations)
- MQLs within 30 days (and rate from registrations)
- Cost per MQL via this content
### Step 5 — Visualize the funnel
The question the chart needs to answer: **which paid channels generate the highest-quality registrations for this content?**
A grouped horizontal bar chart per channel, with bars for each funnel stage (register, attend, MQL within 30 days) sized by conversion rate, surfaces where the drop-off happens per channel. Sometimes a channel has high registration rates but low attendance — the content didn't deliver against expectations. Other times the inverse.
A secondary view: cost-per-MQL bar chart per channel via this content asset, compared to the user's overall cost-per-MQL baseline. Surfaces whether this content is more or less efficient than the user's blended acquisition.
### Step 6 — Output
Use `assets/integrated_funnel_summary.md` (same template — the structure works for both Workflow 6 and 7). For high-stakes content (annual flagship report, major webinar), the doc may justify the `pptx` skill for a recap deck.
### Common variations
- **Multi-asset analysis** — instead of one content asset, compare 5-10 across the same time period. Which content assets are the highest-converting?
- **By topic or persona** — group content by topic or target persona; see which themes resonate at the highest conversion rates.
- **Live vs on-demand webinar** — many webinars have a live event then an on-demand version. The on-demand conversion rate tends to be different (and is often where the volume actually comes from). Surface both.
---
## Ad hoc analysis
For one-off questions outside these seven workflows ("do leads from landing page A have different MQL rates than from B?", "is there a day-of-week effect on lead quality?", "which landing pages are the highest-MQL-converting destinations for paid traffic?"), write fresh analysis code. The "Choosing the right visualization" framework in the SKILL.md tells you which chart family fits which type of question.
---
## A note on the demand gen audience
Demand gen sits between marketing and sales — two audiences with different vocabularies. Marketing leaders want efficiency framed as CPA and ROAS; sales leaders want it framed as cost per MQL, cost per opp, pipeline contribution. When the deliverable is for sales, translate up the funnel. When it's for marketing, platform-level metrics are fine.
## Background
Chart choices, principles and gotchas for this area: [references/field-marketer-guide.md](references/field-marketer-guide.md).
## Before you analyze
- Load saved targets, budgets and known context with `manage_business_context` (`action: get`) and judge results against them, not generic benchmarks.
- Query correctly: follow the `marketing-data-queries` skill for discovery, field IDs and platform quirks.
- Check tracking first. If platform conversions and GA4 or backend numbers disagree by more than 20%, or spend continues with zero conversions, say so before any optimization advice.
- Pull, then analyze, as separate steps. Run one heavy query at a time.
- Evidence discipline: treat changes on fewer than ~10 conversions as noise, ignore items under 1,000 impressions, don't call learning-phase campaigns failures, check for shared budgets before budget advice, and re-pull before conceding a disputed number.
- Answer shape: conclusion, business impact, next actions, then "How I got this" (one line per data pull).
- Helper scripts in `scripts/` take a CSV and print a table. Run them if you can execute code; otherwise compute the same thing directly. Templates in `assets/` shape the final deliverable.
## After the analysis
- Analysis only recommends. If the user wants to act (pause, budget shift, negatives), use the `campaign-management` skill, with explicit approval for each change.
- For a recurring or shareable result, offer once to publish it as a live Supermetrics Studio dashboard with `manage_dashboards` (static preview first, then the live upload).
Referenced files: 19 — file references are metadata, not package contents.
executive-marketing-report19.6 KB
View saved version →
---
name: executive-marketing-report
description: Leadership-level marketing reporting from live data: 90-day executive overviews, efficiency vs goals, CAC and LTV unit economics, annual planning and new-channel business cases, delivered as decks, memos or live Supermetrics Studio dashboards. Use for CMO, board and quarterly updates.
---
# Executive marketing report
## Workflows
### The 90-day executive overview
**When to use:** the user is preparing a quarterly review or cross-channel summary for a CMO, leadership team, or board. The output is usually a slide deck, often accompanied by a printable handout.
**Platforms typically involved:** LinkedIn Ads, Facebook Ads, Google Ads at minimum, often expanded to TikTok Ads, Microsoft Ads, and any display or programmatic platforms the user runs.
### Step 1 — Pull the data
> Pull the last 90 days of performance data from [the connected ad platforms]. Include spend, impressions, clicks, conversions, conversion value or revenue, CPA, and ROAS, broken down by channel and by week.
Weekly granularity matters — trends are visible, not just totals. Leaders often have specific KPIs (MQLs, SQLs, pipeline value) they want surfaced; confirm before going deeper.
### Step 2 — Visualize the headline
The first chart the user sees should answer: **what's the story this quarter?** Build a high-level summary visualization before drilling into channel-level detail.
Options that work well at this layer:
- A small dashboard-style group of headline metric cards (total spend, total revenue, blended ROAS, total conversions) with the period-over-period change next to each
- A simple weekly line chart showing blended ROAS or total spend trend over the 90 days
- A stacked bar showing channel-mix of spend and a paired stacked bar showing channel-mix of revenue (mismatches between the two are the most useful finding)
Pick one — don't build all three. The headline is one thing, not three.
### Step 3 — Channel-level detail
For each channel with meaningful spend, surface the key metrics: spend, revenue, conversions, ROAS, CPA, share of total spend, share of total revenue.
When the comparison is "which channel is pulling its weight?", a side-by-side chart of spend-share vs revenue-share per channel makes mismatches obvious immediately — channels well above the diagonal are over-delivering, channels below it are under-delivering.
### Step 4 — Recommendations
Use `scripts/exec_summary_builder.py` to produce a structured outline of the deck content. The script handles the slide skeleton; the user's analysis fills in the callouts and recommendations.
Build from `assets/exec_deck_outline.md`. Recommendations should be specific: name a channel, name a dollar amount or percent shift, name the expected impact.
### Step 5 — Build the deck
Use the `pptx` skill, if available, to produce the actual `.pptx` file. Read the SKILL.md first — slides have layout rules and visual conventions that don't apply to documents.
Embed the visualizations from steps 2 and 3 inside the deck. Don't put long text on slides — bullets and callouts only. The deck is a talking aid.
### Step 6 — Companion deliverables (only if asked)
For a quarterly review the team will reopen, offer once to publish it as a live Studio dashboard (with `manage_dashboards`). If the user wants a handout to accompany the deck, use the `docx` skill to produce a Google Doc–style summary. If they want a CMO email, build from `assets/cmo_email.md` and deliver inline as markdown (so they can edit before sending). If Gmail is connected, offer to save as a draft.
### Common variations
- **Just the executive summary, skip channel deep-dives** — collapse to one summary visualization + one cross-channel comparison + recommendations.
- **Quarter-over-quarter framing** — pull a second 90-day window from the prior quarter and add a QoQ comparison visualization (slopegraph works well for this).
- **Add a specific campaign deep-dive** — drop in one focused slide between the channel-level section and the cross-channel comparison.
---
### Annual planning support
**When to use:** the user is building the annual marketing budget proposal for next year. The output goes to the CFO or CEO as a defensible recommendation for how to allocate marketing dollars across channels.
**Platforms typically involved:** all connected ad platforms. Optionally CRM (HubSpot, Salesforce) for pipeline contribution, ecommerce backends (Shopify, etc.) for revenue context.
### Step 1 — Pull the long view
> Pull the last 12-15 months of monthly performance data per channel from [the connected ad platforms]. Include spend, conversions, revenue, ROAS, and CPA.
12+ months captures seasonality. If the user can pull 24 months, even better — but most teams' data hygiene gets messy beyond a year.
### Step 2 — Classify channels by behavior
Use `scripts/annual_planner.py`. The script classifies each channel into one of four buckets based on stability and growth:
- **Stable performer** — flat ROAS, predictable volume. Safe to plan budget on.
- **Growing channel** — improving ROAS or growing volume. Candidate for budget expansion.
- **Declining channel** — deteriorating ROAS or volume. Candidate for budget reduction or sunset.
- **Volatile channel** — high variance, hard to predict. Plan conservatively.
### Step 3 — Visualize the channel portfolio
The question the chart needs to answer: **which channels can we count on next year, and which are at risk?**
The most useful visualization here is a quadrant chart with axes: average monthly ROAS (or another efficiency metric) on the y-axis, ROAS volatility (standard deviation across months) on the x-axis. Dots sized by total annual spend. Quadrants tell the story:
- High ROAS, low volatility (top-left) — the keepers
- High ROAS, high volatility (top-right) — promising but risky
- Low ROAS, low volatility (bottom-left) — predictable but draining
- Low ROAS, high volatility (bottom-right) — sunset candidates
A secondary visualization: stacked bar by month showing channel-mix evolution over the year. Where has the user's channel mix actually drifted?
### Step 4 — Model scenarios
Generate 2-3 budget mix scenarios:
- **"Hold" scenario** — same total budget, current channel mix, projected outcomes
- **"Growth" scenario** — total budget +X%, weighted toward growing channels
- **"Efficiency" scenario** — same or smaller total budget, weighted toward stable + growing, sunset the declining ones
For each scenario, project total conversions, total revenue, blended ROAS, and total CAC if CRM data is available.
### Step 5 — Build the annual plan doc
Use `assets/annual_plan_doc.md`. The doc structure: market context (1 page), current-state recap (1 page), channel portfolio analysis (2 pages including the quadrant chart), scenario comparison (2 pages), recommendation with rationale (1 page), risk factors and assumptions (1 page).
Use the `docx` skill to produce the actual Word doc — annual plans get printed, marked up, and circulated. For the slides version, use the `pptx` skill in parallel.
### Common variations
- **Add a "new channels" scenario** — combine with Workflow 5's analytical output for proposing new platforms.
- **Pipeline contribution overlay** — if HubSpot or Salesforce is connected, overlay pipeline-influenced revenue on top of direct-attribution revenue. Often changes the rank order.
- **Multi-year comparison** — if 24+ months of data is available, show 2-year-over-2-year trends rather than month-by-month.
---
### New channel investment case
**When to use:** the user is considering launching on a new platform (Reddit Ads, Pinterest, TikTok, Spotify Ads, retail media platforms, a new DSP) and needs to justify the investment. Often paired with annual planning.
**Platforms typically involved:** current ad platforms (for the saturation analysis) + web search (for benchmark data on the proposed new channel).
### Step 1 — Audit current channel saturation
Audience saturation is the strongest signal that a new channel is worth trying. Pull the last 6 months of CPM, CPC, and frequency trends per current channel.
Use `scripts/channel_investment_case.py` to identify channels showing saturation signals:
- CPM trending up consistently
- Frequency climbing
- CTR trending down at flat or rising CPCs
These are the channels where incremental dollars are getting expensive. If they're showing saturation, a new channel is more likely to outperform incremental spend on the current ones.
### Step 2 — Estimate audience overlap
GA4 doesn't expose cross-channel audience overlap through its reporting API. As a proxy, pull GA4 `newUsers` vs total users by `firstUserDefaultChannelGrouping`: channels still bringing a high share of new users are reaching fresh audiences; a falling share suggests current channels are recycling the same people.
### Step 3 — Research the new channel
Use web search to find recent benchmarks for the proposed new channel: typical CPM, CPC, conversion rate, audience profile. Note the date and source of every benchmark — these change quickly.
If similar companies in the user's category have published case studies on the proposed channel, surface those. Note bias: published case studies are usually success stories.
### Step 4 — Visualize the case
The question the chart needs to answer: **why does this new channel make sense given our current portfolio?**
A useful primary visualization is a stacked or grouped bar chart showing per-channel saturation signals (CPM trend, frequency, CTR trend) over the past 6 months. Channels showing red across multiple signals are saturation cases.
A secondary visualization: a comparison table or bar chart showing the proposed new channel's expected CPM/CPC/conversion rate (from research) against the user's blended current numbers, with the assumption explicitly labeled.
### Step 5 — Build the business case
Use `assets/new_channel_business_case.md`. The case includes:
- The saturation evidence (chart + summary)
- The expected economics on the new channel (with assumptions)
- A proposed test budget and timeline (typically $X for Y weeks)
- Success criteria — what would justify continuing? What would mean we pull out?
- The opportunity cost — what current channel spend is being deprioritized to fund the test?
### Common variations
- **For retail media specifically** — Walmart Connect, Amazon Ads, Criteo Retail Media. These have different economics (much higher CPC but lower-funnel intent). Frame as "incremental ROAS during high-purchase-intent moments" rather than head-to-head with social.
- **For audio (Spotify Ads)** — different audience and creative requirements. Surface the production cost as well as the media cost.
- **For B2B with LinkedIn Lead Gen Forms** — if the user is already on LinkedIn Ads, this is about expanding format usage not adding a channel.
---
### Marketing efficiency vs goals tracking
**When to use:** the user has committed targets — CAC, payback period, MER, or other goals — and needs to track actual performance against them, surface variance, and explain misses.
**Platforms typically involved:** ad platforms + CRM (HubSpot, Salesforce) + ecommerce or payments connector for revenue context.
### Step 1 — Confirm the targets
Ask the user (with a multiple-choice question tool if available): what are the committed targets, and for what time period? Common ones:
- **CAC** — cost per acquired customer
- **MER** (Marketing Efficiency Ratio) — total revenue / total marketing spend
- **Payback period** — months until LTV exceeds CAC
- **Blended ROAS** — sum revenue / sum spend across all marketing
- **CPL** — cost per lead (for B2B)
### Step 2 — Pull and compute actuals
Pull spend from ad platforms, revenue from ecommerce/CRM. Compute the same metrics the user committed to.
Use `scripts/efficiency_tracker.py`. The script accepts the target values and computes:
- Actual value
- Variance from target (absolute and percent)
- Trend direction (improving, holding, declining)
### Step 3 — Visualize the gap
The question the chart needs to answer: **are we on target, and if not, where's the gap?**
A horizontal bar chart with one bar per metric, where each bar shows actual value with the target as a reference line, works well. Color the gap red when over target on a "lower is better" metric (CAC), green when under it. The user sees at a glance which metrics are meeting targets.
A secondary visualization: a small line chart per metric showing the trailing 90-day trend, with the target as a horizontal reference line. Surfaces whether the gap is widening, holding, or closing.
### Step 4 — Diagnose
For each metric that's missing target, surface 2-3 likely causes from the underlying data:
- CAC too high → which channels are driving the average up?
- Payback period too long → has AOV dropped, or has new-customer CAC risen?
- MER too low → has total revenue declined, or has total spend risen disproportionately?
Use `assets/efficiency_dashboard_doc.md` for the structured output.
### Step 5 — Output
Default delivery: chart + diagnosis inline as markdown. If the user is sharing this with their leadership team monthly or quarterly, use the `docx` skill.
### Common variations
- **Cohort-level CAC** — if the user has month-of-acquisition cohorts, compute CAC per cohort rather than blended. Surfaces whether recent cohorts are getting more expensive to acquire.
- **Channel-attributed CAC** — split blended CAC into per-channel CAC using a defined attribution model. State which model.
- **CAC payback by cohort** — for SaaS or subscription businesses, this is the real question. Cohort revenue over time vs. cohort acquisition cost.
---
### CAC and LTV unit economics
**When to use:** the user wants the finance-team view of marketing — what does it cost to acquire a customer, what are they worth over their lifetime, what's the LTV:CAC ratio. The deliverable typically goes to a CFO, board, or investor.
**Platforms typically involved:** ad platforms (for CAC numerator) + CRM (HubSpot, Salesforce, Pipedrive) and/or ecommerce/payments (Shopify, Stripe, Recharge) for LTV. This workflow is significantly more valuable when both sides are connected.
### Step 1 — Confirm what counts as a customer
Ask the user (with a multiple-choice question tool if available): which event defines "acquired customer"?
- First purchase (ecommerce default)
- Closed-won opportunity (B2B default)
- Subscription start (SaaS default)
- Form fill + qualification (lead-gen heavy businesses)
Also confirm the LTV horizon: 12-month LTV is common, 24-month gives a fuller picture for SaaS.
### Step 2 — Pull CAC numerator (marketing spend)
> Pull total marketing spend for the last [12-24] months across [all connected ad platforms].
Optionally include other marketing costs (tools, content production) if the user wants a fully-loaded CAC — but state that clearly in the output.
### Step 3 — Pull CAC denominator and LTV (customers and revenue)
Pull customer acquisition counts and revenue from the CRM or ecommerce backend over the same period.
For ecommerce: cohort customers by first-purchase month, sum their cumulative revenue over the horizon.
For B2B: cohort customers by closed-won month, sum closed-won revenue + expansion revenue over the horizon.
### Step 4 — Compute unit economics
Use `scripts/unit_economics.py`. Outputs:
- Blended CAC (total marketing spend / total new customers in the period)
- Per-channel CAC: run the script once per channel's cohort data
- LTV (cumulative revenue per acquired customer)
- LTV:CAC ratio (3:1 is the SaaS rule of thumb; 4:1+ is healthier for venture-funded businesses)
- Payback period (months until LTV exceeds CAC)
### Step 5 — Visualize the unit economics
Two charts that work together:
- **Cohort LTV curve**: x-axis = months since acquisition, y-axis = cumulative revenue per customer. One line per acquisition cohort. The shape of these curves is the most important visualization in unit economics — flat curves mean low retention, steep curves mean strong retention.
- **CAC vs LTV bars by channel**: paired bars per channel showing CAC and LTV. The gap between the pairs is the channel-level contribution margin.
### Step 6 — Build the finance-ready doc
Use the `docx` skill. The doc should be one page if possible, with:
- Headline LTV:CAC ratio and trend (improving/stable/deteriorating)
- The cohort LTV chart
- Per-channel unit economics if available
- Assumptions: what's included in "marketing spend", what's the LTV horizon, what attribution is used for per-channel CAC
- A note that this is a snapshot of past cohorts; forward projections require additional assumptions
### Common variations
- **Subscription business** — pull monthly recurring revenue (MRR) cohorts rather than total revenue. The chart becomes MRR retention curves, which is the standard SaaS view.
- **Heavy seasonality** — overlay multiple acquisition-quarter cohorts to see whether different acquisition periods have systematically different LTV.
- **By acquisition channel** — when ad-platform → CRM customer ID linkage is available, compute per-channel LTV. Often shows that the cheapest CAC channels have the worst retention.
---
## Ad hoc analysis
For one-off leadership questions outside the seven workflows above ("what's the concentration of spend across our top 3 vs the rest?", "is there a launch-month effect on new campaigns?", "how did our CPA trend during the last price change?"), write fresh analysis code in the chat. The "Choosing the right visualization" framework in the SKILL.md tells you which chart family fits which type of question.
---
## A note on the leadership audience
Three patterns that consistently work when the audience is a marketing leader:
- **Headline → support → recommendation.** Open every deliverable with one sentence that summarizes the whole thing. Then the data. Then what to do about it.
- **Specific dollar amounts beat percentages.** "Shift $40k to LinkedIn next month" lands harder than "shift 20% of the budget." Use percentages in headlines, dollars in recommendations.
- **Name the trade-off.** Every recommendation cuts something. If you don't name it, the audience will, and the conversation will pivot to that instead of the recommendation. Get there first.
## Background
Chart choices, principles and gotchas for this area: [references/marketing-leader-guide.md](references/marketing-leader-guide.md).
## Before you analyze
- Load saved targets, budgets and known context with `manage_business_context` (`action: get`) and judge results against them, not generic benchmarks.
- Query correctly: follow the `marketing-data-queries` skill for discovery, field IDs and platform quirks.
- Check tracking first. If platform conversions and GA4 or backend numbers disagree by more than 20%, or spend continues with zero conversions, say so before any optimization advice.
- Pull, then analyze, as separate steps. Run one heavy query at a time.
- Evidence discipline: treat changes on fewer than ~10 conversions as noise, ignore items under 1,000 impressions, don't call learning-phase campaigns failures, check for shared budgets before budget advice, and re-pull before conceding a disputed number.
- Answer shape: conclusion, business impact, next actions, then "How I got this" (one line per data pull).
- Helper scripts in `scripts/` take a CSV and print a table. Run them if you can execute code; otherwise compute the same thing directly. Templates in `assets/` shape the final deliverable.
## After the analysis
- Analysis only recommends. If the user wants to act (pause, budget shift, negatives), use the `campaign-management` skill, with explicit approval for each change.
- For a recurring or shareable result, offer once to publish it as a live Supermetrics Studio dashboard with `manage_dashboards` (static preview first, then the live upload).
Referenced files: 13 — file references are metadata, not package contents.
funnel-and-tracking-audit9.19 KB
View saved version →
---
name: funnel-and-tracking-audit
description: Reconcile what ad platforms report with what GA4 and the CRM or store recorded, find tracking breaks, implausible CPAs and broken UTMs, and diagnose where traffic leaks between click and conversion. Use before trusting optimisation advice, or when platform and GA4 numbers disagree.
---
# Funnel and tracking audit
## Workflows
### The traffic-to-conversion audit
**When to use:** the user wants to see which channels drive engaged traffic that actually converts on-site, not just cheap clicks. The output usually ends with an update to sales leadership justifying a budget reallocation.
**Platforms typically involved:** Google Ads, LinkedIn Ads, and Google Analytics 4. GA4 is mandatory — without it this workflow can't run.
### Step 1 — Pull ad platform data, then GA4
> Pull the last 30 days of spend and click data from the Google Ads and LinkedIn Ads accounts. Then pull sessions and key events (conversions) for the same period from Google Analytics 4, by session source / medium.
Two separate pulls. Do ad platforms first, confirm the data, then GA4 split by `sessionSourceMedium` or `sessionCampaignName` (not default channel grouping, which lumps LinkedIn and Facebook into "Paid Social"). Map GA4 rows to the same channel names as the ad data before reconciling. If GA4 isn't connected, stop and tell the user this workflow requires it.
### Step 2 — Reconcile
Use `scripts/funnel_reconciler.py --ad-platform ads.csv --ga4 ga4.csv`. The script joins by channel name (the `channel` column in both files must use identical values) and computes the divergence between platform-reported and GA4-measured outcomes. Channels where the click-to-session gap exceeds 25% get flagged as likely UTM/tracking issues.
### Step 3 — Visualize the reconciliation
The question the chart needs to answer: **where's the leak — is each channel converting the traffic it bought, or losing it somewhere?**
For a small number of channels (3–5), a paired bar chart per channel works well: one bar for the ad platform metric (e.g. platform-reported CPA), one bar for the GA4 measurement of the same thing (GA4-measured CPA). Big gaps between the pairs are the story. Channels with tracking flags get an amber outline.
When the user wants the funnel view explicitly, a descending bar chart showing impressions → clicks → sessions → conversions makes drop-off rates visible at each stage.
Whichever you build, name the headline above the chart — "Two of four channels have tracking issues" or "Facebook traffic doesn't convert post-click" — don't make the user infer the story.
### Step 4 — Recommendation
> Write a short paragraph recommending how budget should be reallocated next period to prioritize the channel driving the highest-quality website traffic.
The recommendation should name a specific dollar amount, a source channel, a destination channel, and the expected impact on **GA4-measured** conversions (not just ad-platform conversions — that's the whole point).
### Step 5 — Update sales leadership
Build from `assets/sales_leadership_email.md`. Default delivery is markdown inline. If the user wants it as a Word doc, use the `docx` skill. If Gmail is connected, offer to save as a draft. If leadership wants to see this every month, offer to publish it as a live Studio dashboard (see the `manage_dashboards`).
### Common variations
- **Adobe Analytics instead of GA4** — same workflow shape; Supermetrics has Adobe Analytics support, ask whether it's connected.
- **Use last-click instead of GA4's default attribution** — GA4's default is data-driven; the model is a property-level setting, so the API returns whatever the property uses. Session-scoped dimensions (`sessionSourceMedium`) are last-click by nature; ask the user which view they want and note the choice in the deliverable.
- **Join with CRM lead-quality data** — if HubSpot or Salesforce is connected, pull MQL conversion rate by source and join with the reconciliation. The combined view ("$50 ad CPA + 8% MQL rate" vs "$80 ad CPA + 35% MQL rate") changes the recommendation entirely.
---
### Landing page performance diagnosis
**When to use:** the user wants to find which content pages get traffic but fail to convert it, and document the fixes for the web/dev team.
**Platforms typically involved:** Google Analytics 4 (mandatory).
### Step 1 — Pull page-level data
> Pull the top 20 landing pages by traffic volume from Google Analytics 4 over the last 30 days, including bounce rate, average engagement time, and key events (or session key event rate).
Default to top 20 — that's the right unit for "where is the leak?" because it weights toward pages where fixes will have visible impact. Expand if the user wants a deeper audit.
### Step 2 — Identify underperformers
Use `scripts/landing_page_diagnoser.py` (columns: `page_path`, `sessions`, `bounce_rate` and `conversion_rate` as percentages, `avg_time_on_page` in seconds; it accepts `conversions` instead of a rate). Default thresholds are 70% bounce rate and 1% conversion rate, with a 500-session minimum. Ask the user about their baselines — these vary by industry (a B2B SaaS landing page should convert higher than a blog post).
### Step 3 — Visualize the diagnosis
The question the chart needs to answer: **which pages should the web team fix first, and why?**
The most useful visualization for this is usually a quadrant chart: sessions on the x-axis, conversion rate on the y-axis. The bottom-right quadrant (high traffic, low conversion) is the priority. The top-right is winners worth studying. Pages get sized or colored by lost-opportunity score (sessions × conversion gap) so the user sees impact at a glance.
When the user wants a ranked list rather than a quadrant view, a sorted horizontal bar chart of lost-opportunity score works well — bars sorted descending, top 5 highlighted as priority.
Reference lines on either chart for the conversion target and bounce-rate threshold make the cut-offs visible without explanation.
### Step 4 — Diagnose likely causes
For each priority page, list 2–3 specific reasons it might be underperforming based on standard UX principles:
- Slow page load, especially on mobile
- Confusing or missing primary CTA
- Headline doesn't match search intent or ad copy driving the traffic
- Form too long or asking for too much info
- Above-the-fold content doesn't deliver on the page title's promise
- Mobile experience broken (form fields too small, buttons cut off)
- No social proof or trust indicators near the CTA
- Above-the-fold ads or popups that interrupt
- Search intent vs page intent mismatch
Pick fixes appropriate to the page type — a blog post needs different fixes than a product landing page.
### Step 5 — Build the web team doc
Use `assets/web_team_doc.md` for structure. The doc needs to be a checklist the web team can act on: page URL, current state, proposed fix, estimated effort, expected impact.
Default delivery: build it as a Word doc with the `docx` skill — the web team will print or share it. If the user prefers Drive, save it there if Google Drive is connected. If they want a spreadsheet to track checkboxes, use the `xlsx` skill instead.
### Common variations
- **CMS or HubSpot tracks conversions, not GA4** — same workflow shape; pull form views and submissions from HubSpot Marketing Forms (`HSMF`) or page data from HubSpot Content Analytics (`HSCA`) if connected, then join to the GA4 page list by URL.
- **Just blog posts, not landing pages** — filter URLs containing `/blog/` (or the user's blog path) in step 1.
- **Mobile only** — re-pull GA4 data with device category as a filter.
---
## Background
Chart choices, principles and gotchas for this area: [references/demand-gen-guide.md](references/demand-gen-guide.md), [references/content-marketer-guide.md](references/content-marketer-guide.md).
## Before you analyze
- Load saved targets, budgets and known context with `manage_business_context` (`action: get`) and judge results against them, not generic benchmarks.
- Query correctly: follow the `marketing-data-queries` skill for discovery, field IDs and platform quirks.
- Check tracking first. If platform conversions and GA4 or backend numbers disagree by more than 20%, or spend continues with zero conversions, say so before any optimization advice.
- Pull, then analyze, as separate steps. Run one heavy query at a time.
- Evidence discipline: treat changes on fewer than ~10 conversions as noise, ignore items under 1,000 impressions, don't call learning-phase campaigns failures, check for shared budgets before budget advice, and re-pull before conceding a disputed number.
- Answer shape: conclusion, business impact, next actions, then "How I got this" (one line per data pull).
- Helper scripts in `scripts/` take a CSV and print a table. Run them if you can execute code; otherwise compute the same thing directly. Templates in `assets/` shape the final deliverable.
## After the analysis
- Analysis only recommends. If the user wants to act (pause, budget shift, negatives), use the `campaign-management` skill, with explicit approval for each change.
- For a recurring or shareable result, offer once to publish it as a live Supermetrics Studio dashboard with `manage_dashboards` (static preview first, then the live upload).
Referenced files: 8 — file references are metadata, not package contents.
get-started2.83 KB
View saved version →
---
name: get-started
description: First-run onboarding for Supermetrics. Use right after the user connects Supermetrics, when they ask how to get started or what data they can access, when they want to connect Google Ads, Meta, GA4, LinkedIn or another platform, or when a Supermetrics call fails because they aren't signed in or a source isn't connected.
---
# Get started with Supermetrics
Take the user from install to their first real answer in as few turns as possible. Do each step only if the previous one succeeded.
## 1. Check sign-in
Call `manage_user_and_team` with `action: get_info`.
- **Tool not available or auth error:** the Supermetrics connector isn't connected or signed in. Ask the user to connect or reconnect Supermetrics in their AI app's connector or app settings and sign in with their Supermetrics account (new users get a 14-day free trial, no card). Then stop and wait. Never ask for an API key or password in chat.
- **Signed in, but `license` holds an error, or a tool returns a license or trial error:** don't loop on sign-in. Say so plainly and follow the note in the response; buying is at https://supermetrics.com/pricing, and the plan must include the AI Chats destination. For details, call `supermetrics_guide` with `mode: license_and_trials`.
- **Success:** greet them by name and team in one line.
## 2. See what's connected
Call `data_source_discovery` with `compress: true`; each source's `authentication_status` shows what's connected. Then call `accounts_discovery` for the connected platforms the user cares about. Summarise in one short list: connected platforms and account counts. Don't dump every source.
If nothing relevant is connected, ask which platform they want first (Google Ads, Meta Ads, GA4, LinkedIn Ads, TikTok Ads, Microsoft Ads, Shopify, HubSpot…) and call `manage_user_and_team` with `action: login_data_source` and its `ds_id`. Give them the login link and wait. Never describe clicking through menus; hand over the link. For platform-specific connection help, call `supermetrics_guide` with `mode: connect_data_source`.
## 3. First answer
Once at least one account is connected, run one small useful report straight away — last 7 days vs the previous 7 for spend, clicks, conversions and cost per conversion (or sessions and conversions for GA4) — and show it as a compact chart or table.
## 4. Save their goals
Ask what they're optimizing for (target CPA, ROAS or monthly budget). Save it with `manage_business_context` (`action: save`, tags like `targets`) so later analyses judge results against it. Skip this if a profile already exists.
## 5. Point to what's next
Suggest three questions tailored to what they connected, for example a wasted-spend audit, a weekly performance review, budget pacing, or launching a campaign. Mention that results can be published as a live Supermetrics Studio dashboard.
Referenced files: 2 — file references are metadata, not package contents.
live-dashboards7.12 KB
View saved version →
---
name: live-dashboards
description: Plan, build and publish live, shareable marketing dashboards in Supermetrics Studio with manage_dashboards — pages that re-query the user's data on every view and can include campaign management actions. Use when the user asks for a dashboard, a report the team can reopen, a shareable link, or a recurring view (weekly review, pacing, KPIs), and to edit or find existing Studio dashboards.
---
# Live dashboards in Supermetrics Studio
A Studio dashboard is a page stored in Supermetrics Studio that fetches the user's data every time someone opens it, so a shared link always shows current numbers. Dashboards aren't limited to reading data: they can also include campaign management, such as pausing or enabling a campaign or changing a budget straight from the page. The `manage_dashboards` tool uploads, reads, edits and lists them.
**The `manage_dashboards` tool description and its parameter descriptions are the technical source of truth.** Follow them exactly for the code: how to call `smQuery`, how to parse its response, region markers, query keys, date and comparison parameters, `allowed_tools`, `allowed_accounts`, patch types and BigQuery. This skill covers when to offer a dashboard, how to plan it, and what makes it useful.
## When to use
- The user asks for a dashboard, a live report or a link to share.
- An analysis will be reopened: a weekly performance review, a daily check, budget pacing, a monthly SEO or channel review, a client report. Offer a live dashboard once at the end of that analysis; don't push it again if declined.
- The user wants to change, find or see the history of a dashboard they already have.
A one-off question needs a table or chart in the chat, not a dashboard.
## Workflow: new dashboard
### 1. Agree what it's for
Settle this in one short exchange at most, using what the conversation already tells you:
- **Question it answers** — "are we on budget this month?", "how did paid media do this week?", "which campaigns need attention?". One dashboard, one main question.
- **Audience** — the user, their team, leadership or a client. Leadership wants few numbers and trends; a media buyer wants campaign-level detail.
- **Sources and accounts** — which data sources and account IDs. Use `data_source_discovery` and `accounts_discovery` if not known.
- **Controls** — a date range by default; account, channel or campaign selectors and a period comparison if the audience will use them.
- **Actions** — whether viewers should be able to act on what they see, for example pause a campaign from the table or adjust a budget next to its pacing figure.
### 2. Prove the data first
Run each query once with `data_query` and `get_async_query_results`, using exact field IDs from `field_discovery`. Fix wrong fields, missing accounts or connection errors now; a broken query inside a published dashboard only shows an error to every viewer. The results also feed the preview.
### 3. Show a static preview
Build the dashboard with the numbers from step 2 written in and show it in the chat. Keep it close to what will be published, so the user is approving the real layout.
### 4. Confirm, then publish
Ask whether to publish it as a live Studio dashboard, unless the user already asked for a link. Then rebuild the data layer for Studio as the tool instructions describe and upload. Never upload the static preview.
### 5. Hand it over
Check the upload response and act on anything the tool instructions say to fix before sharing. Then give the user the link and one sentence on how to use it ("updates on every view; change the date range at the top").
## Workflow: change an existing dashboard
1. Find it with `list` (filter by a word from the title) unless you have its ID.
2. `get` the current code, then `edit` with the smallest patch that does the job, as the tool instructions describe. Add a short `change_summary`.
3. Use `changelog` when the user asks what changed or when.
## Campaign management in dashboards
A dashboard can act as well as report: a campaign table with pause and enable buttons, a pacing view where budgets can be adjusted, or a wasted-spend view with a one-click pause for the worst offenders.
- Add actions when the user asks for them or when the dashboard's purpose is to act (pacing, wasted spend, daily checks). Read-only is the default for leadership and client dashboards.
- Include the campaign tools the page calls in `allowed_tools` (for example `campaign_and_resource_get` and `manage_campaign`), and only the accounts it manages in `allowed_accounts`, as the tool instructions describe.
- Follow the `campaign-management` skill for the write itself: read the current state first, send only the fields that change, and check `write_status` in the result.
- Make every action deliberate: name the campaign and the exact change in a confirmation step before it runs, then show the result or the error in the page.
- The account's write settings and approval rules still apply. If a change needs approval, show that it is waiting instead of reporting it as done.
- Viewers act through the dashboard owner's connections, so tell the user that anyone they share an action dashboard with can make those changes, and suggest sharing it only with the people who should.
## What makes a good marketing dashboard
**Order: headline, trend, detail.** Three to six KPI cards on top, one or two trend charts below, then a table for drill-down. Someone who only reads the top row should still get the answer.
**Pick KPIs for the question:**
- Paid media performance — spend, conversions, cost per conversion, ROAS or conversion value, CTR.
- Budget pacing — month-to-date spend against budget, projected month-end spend, daily run rate, by channel.
- Ecommerce — revenue, orders, blended ROAS, average order value, new vs returning customers.
- Lead generation and B2B — leads, cost per lead, MQLs or pipeline by channel.
- SEO and content — clicks, impressions, average position and CTR from Search Console; sessions and conversions by landing page.
- Leadership summary — a handful of business numbers against the previous period or target, no campaign tables.
**Compare, don't just report.** A number is meaningful next to the previous period, the same period last year or a target. Add a period comparison when the audience asks "is this good?".
**Show direction by business meaning.** Green for good, red for bad: falling CPA is green even though the number went down.
**Use the account currency and clear formatting** — currency symbols, thousands separators, percentages with one decimal.
**Make the tables useful.** Sort by what matters (spend or conversions), show the top rows, and include the efficiency column (CPA, ROAS) next to the volume columns.
**Keep cross-channel numbers honest.** When combining platforms, use the same metric definitions and say where platform-reported conversions differ from GA4 or the CRM.
**Name it so it's findable later** — what, for whom, how often: "Paid media weekly — Acme", "Budget pacing — EMEA".
**Share carefully.** Viewers see data through the owner's connections, so scope `allowed_accounts` to exactly the accounts the dashboard shows, as the tool instructions require.
Referenced files: 2 — file references are metadata, not package contents.
marketing-data-queries5.74 KB
View saved version →
---
name: marketing-data-queries
description: How to query live marketing data through Supermetrics without failed queries — discovery, report types, field IDs, date ranges, filters and reading results — for Google Ads, Meta Ads, GA4, LinkedIn Ads, TikTok Ads, Microsoft Advertising, Instagram, Shopify, HubSpot, Search Console and every other connected source. Use before any data_query, for cross-channel or blended questions, and whenever a query errors or returns no data.
---
# Querying marketing data with Supermetrics
Never answer a performance question from memory. Supermetrics returns live data — query it.
## Platform references
Before querying one of these platforms, read its reference file for field IDs, report types, combinations that fail and data-freshness lags:
| Platform | Reference |
|---|---|
| Google Ads (`AW`) | [references/google-ads.md](references/google-ads.md) |
| Meta Ads (`FA`) | [references/meta-ads.md](references/meta-ads.md) |
| Google Analytics 4 (`GAWA`) | [references/google-analytics-4.md](references/google-analytics-4.md) |
| LinkedIn Ads (`LIA`) | [references/linkedin-ads.md](references/linkedin-ads.md) |
| TikTok Ads (`TIK`) | [references/tiktok-ads.md](references/tiktok-ads.md) |
| Microsoft Advertising (`AC`) | [references/microsoft-ads.md](references/microsoft-ads.md) |
| Instagram Insights (`IGI`) | [references/instagram-insights.md](references/instagram-insights.md) |
For any other source, use the workflow below with `field_discovery`.
## The workflow
Follow these steps in order. Skipping discovery is the most common cause of failed queries.
1. **`data_source_discovery()`** — list sources and their auth status. Pick the one the
user means. If they say "Facebook" or "Meta", that is `FA`; "Google Ads" is `AW`;
"GA4" is `GAWA`.
2. **`data_source_discovery(ds_id=X)`** — read that source's configuration before
querying. It tells you what the next steps must be:
- `has_account_list: true` → call `accounts_discovery(ds_id=X)` for account IDs.
- `has_report_type_selection: true` → choose a `report_type` and pass it in `settings`.
- `has_fields: true` → call `field_discovery(ds_id=X)` to get valid field IDs.
- `is_date_range_required: true` → set a date range (nearly always true).
3. **`field_discovery(ds_id=X, filter="...")`** — filter rather than dumping every field.
`filter="cost,click,conversion"` is far more useful than the full catalogue.
4. **`data_query(...)`** — dimensions before metrics in `fields`. All fields must belong
to the same report type.
5. **`get_async_query_results(schedule_id=...)`** — if the query returns a schedule ID
instead of rows, poll immediately and keep polling until `completed`.
## Business context
Before analyzing a specific account, call `manage_business_context` with `action="get"`
and the `ds_id` (plus `account_id` where relevant). Teams store reporting conventions
there — which campaigns to exclude, which attribution window to use, how to segment.
Applying them is the difference between a correct answer and a plausible one.
If the user states a durable preference mid-conversation ("always exclude brand
campaigns", "we report in EUR"), offer to save it with `action="save"`.
## Writing good queries
- **Dates**: prefer relative ranges (`last_30_days`, `last_month`, `this_month_inc`).
For anything relative to "now", call `get_today` first — do not assume the date.
- **Comparisons**: `compare_type="prev_range"` or `"prev_year"` answers "how does that
compare?" in one query instead of two. Other values: `prev_year_weekday`, or `custom` with
`compare_start_date`/`compare_end_date`. `compare_show` picks `perc_change` (default),
`abs_change` or `value`.
- **Filters**: `filters="country == US AND clicks > 100"`. Operators include `==`, `!=`,
`>`, `>=`, `=@` (contains), `=~` (regex), `[]` (in list).
- **Row limits**: default is 1000. Raise `max_rows` for long date ranges broken out by day.
## Reading results
Rows come back as a 2D array: row 0 is display headers, rows 1+ are data. Map columns by
`requested_field_ids`, **not** by the row-0 labels — the labels are human-readable names
that differ from field IDs (`screenPageViews` displays as "Views"), so matching on labels
silently reads the wrong column.
**Check `canonical_field_ids` too.** Supermetrics resolves loose field names through an alias
layer, so a name you guessed can succeed while quietly returning a *different* metric instead of
erroring — asking Meta Ads for `purchases` returns `action_omni_purchase` (web, app and in-store),
not website purchases. When `canonical_field_ids` is present and differs from what you requested,
report the metric that actually came back.
Values may be strings. Parse numbers before arithmetic. An empty cell is `null`, not zero — say
"no data" rather than reporting it as a zero.
If the response carries a `currency_recommendation`, the monetary columns have no currency attached.
Add the currency dimension it names before stating an amount.
## Interpreting, not just reporting
A table is not an answer. After retrieving data:
- Lead with what changed and why it matters, not with the numbers.
- Compare against a baseline — prior period, prior year, or the account average.
- Flag anomalies: sudden CPA moves, campaigns with spend but no conversions, sources
whose data ends before the requested range (often a broken connection, not a real zero).
- Say when a number is unreliable — GA4 sampling, incomplete last day, thresholding.
## When something fails
Call `supermetrics_guide` with the matching `mode` before escalating: `no_data`,
`data_discrepancies`, `ga4_data`, `query_errors`, `reconnect`, `prioritized_accounts`,
`quotas_and_limits`. Most failures are configuration, not bugs, and the guide resolves
them without a support ticket.
Referenced files: 9 — file references are metadata, not package contents.
seo-and-content-performance21.1 KB
View saved version →
---
name: seo-and-content-performance
description: Content and SEO analysis from live data: Search Console and organic performance, content-to-conversion attribution, paid promotion of content, newsletters, video and content gaps. Use for SEO audits, content ROI and editorial planning.
---
# Seo and content performance
## Workflows
### Paid promotion content analysis
**When to use:** the user is deciding which content assets deserve the majority of next quarter's paid promotion budget. Usually triggered by quarterly planning or after a batch of new content has accumulated data.
**Platforms typically involved:** LinkedIn Ads and Facebook Ads primarily. Google Ads sometimes if promoting content in search.
### Step 1 — Pull the data
> Pull the last 60 days of LinkedIn Ads and Facebook Ads campaigns promoting downloadable content, filtered to campaigns containing [the user's naming convention — Content_, Whitepaper_, Ebook_, etc.].
Ask the user about the naming convention if it's unclear. Data should be at the ad / asset level, not just campaign level.
### Step 2 — Rank the assets
Use `scripts/content_promotion_ranker.py` (columns: `asset_name`, `platform`, `spend`, `clicks`, `impressions`, optional `leads`; `--min-spend` defaults to 100). The script ranks by composite engagement (CPC + CTR + lead rate where available) and outputs a sorted list.
A note on metrics: CPC and CTR are engagement metrics, not conversion metrics. They tell you the audience is interested. Whether the asset converts that interest into a lead is a separate question. For ranking which assets to put paid behind, engagement is the right framing.
### Step 3 — Visualize the ranking
The question the chart needs to answer: **which assets are worth more paid budget, and why?**
A sorted horizontal bar chart of the composite promotion score works well as the primary visualization, with bars colored by asset type (whitepaper, ebook, guide, report) so format trends are visible.
If the user wants the multi-dimensional view, a grouped bar chart with one cluster per asset showing CPC, CTR, and lead rate side-by-side surfaces the trade-offs — an asset might win on CTR but lose on lead rate.
### Step 4 — Qualitative read on the winners
> Identify the top two best-performing assets and explain why their messaging is likely resonating with the target audience.
This is the most useful part of the output for next-quarter content planning. Look at the winning assets and identify the actual angle — pain point, social proof, transformation, status, ROI. Use `assets/content_promotion_brief.md` to structure the deliverable. When the user picks which assets to fund, the `campaign-management` skill can apply the budget changes with their approval.
### Step 5 — Output
Default: markdown inline. If the user wants a doc to share with leadership for next-quarter planning, use the `docx` skill.
### Common variations
- **Organic vs paid** — different workflow; organic and paid content perform on different signals. Suggest running paid first, then a separate organic audit.
- **Include cost per lead, not just engagement** — if the user has lead-volume data per asset, the ranker accepts it. But sample sizes get small fast at the asset level for leads; CPC/CTR usually has more reliable signal.
---
### Organic content and SEO performance audit
**When to use:** the user wants to understand which content is winning vs decaying in organic search. Identifies posts to expand, posts to update, and posts to sunset.
**Platforms typically involved:** Google Search Console (`GW`, mandatory) + Google Analytics 4 (`GAWA`, for engagement on top of impressions/clicks). Optional: Ahrefs (`AHRF2`) or Semrush (`SR`) for keyword positions and backlink data, Bing Webmaster Tools (`BW`) for Bing coverage.
### Step 1 — Pull search performance over time
> Pull the last 6-12 months of Search Console performance by page (and query if needed): impressions, clicks, average position, CTR, split by month. Search Console keeps 16 months of data.
For posts published in the last 6 months, the trend captures the launch curve (newer posts haven't matured yet). For older posts, the trend captures growth vs decay.
### Step 2 — Pull on-page engagement
> Pull GA4 data for the same pages (landing page): sessions, engaged sessions, average engagement time, key events.
If GA4 has key events on the relevant actions (form fills, newsletter signups, demo bookings), pull those per page. Search Console reports full URLs while GA4's `landingPage` is a path; normalize before joining.
### Step 3 — Classify each page
Use `scripts/seo_audit.py` (columns: `page`, `month` as YYYY-MM, `impressions`, `clicks`, `average_position`, optional `sessions`, `engaged_sessions`, `conversions`). The script classifies each page into:
- **Growing**: impressions and clicks trending up
- **Stable**: predictable monthly volume
- **Decaying**: impressions or clicks trending down significantly (often signals stale content)
- **Stuck on page 2-3**: average position 11-30 (fixable with on-page work)
- **Underperforming**: engagement rate under 30% despite traffic (content-quality issue; needs the GA4 columns)
### Step 4 — Visualize the portfolio
The question the chart needs to answer: **which pages are growing, which are at risk, and where should I focus content effort?**
A scatter plot works well: x-axis = monthly impressions trend (% change), y-axis = monthly clicks trend. Dots sized by current monthly clicks, colored by classification. The user sees at a glance which pages are climbing and which are slipping.
A secondary view: top 20 decaying pages ranked by absolute click loss vs peak month. These are the urgent updates.
### Step 5 — Build the audit report
Use `assets/seo_audit_report.md` (offer a live Studio dashboard via the `manage_dashboards` if the user wants to track this monthly). The recommendations should split into:
- **Update now** (decaying pages with high historical traffic)
- **Refresh** (stable pages that could grow with a content refresh)
- **Sunset** (low-traffic, low-quality pages dragging average performance)
- **Expand** (growing pages where related content could capture additional queries)
### Common variations
- **Add backlink context** — if Ahrefs is connected, pages with strong backlinks deserve preservation effort; pages with no backlinks may be sunset candidates.
- **Compare to competitors** — if Semrush or Ahrefs is connected, surface which competitor pages outrank the user's on key queries; gives a roadmap for what the user's pages need to address.
- **Branded vs non-branded** — separate branded query performance from non-branded. Branded performance is a vanity metric for content; non-branded is the real test.
---
### Content-to-conversion attribution
**When to use:** the user wants to credit specific content pieces with influencing conversions — not just direct-conversion attribution, but the broader "what content moved this person closer to converting" question.
**Platforms typically involved:** Google Analytics 4 (content engagement) + CRM (HubSpot, Salesforce) for the conversion side when available.
### Step 1 — Pull content engagement
> Pull GA4 data for content URLs: sessions, engaged sessions, average engagement time, scrolled users (90% scroll, if enhanced measurement is on), and key events.
For pages that aren't conversion targets (blog posts, resource pages, podcast pages), engagement signals matter more than conversions.
### Step 2 — Pull touch data
GA4 path explorations and conversion paths are UI-only; the GA4 API doesn't return page-level paths. Use what the API does give:
- **First touch:** GA4 `landingPage` with key events, or HubSpot contact `first_page_seen` / `first_conversion` (`HSCON`).
- **Last touch:** HubSpot contact `recent_conversion` (the last form and page before converting).
- **Middle touch:** only from the CRM's page-view history or an export the user provides. If unavailable, say so and score on first and last touch only.
### Step 3 — Compute the content attribution table
Use `scripts/content_attribution.py` (columns: `content_url`, `sessions`, `engaged_sessions`, optional `avg_engagement_time_seconds`, `first_touch_conversions`, `middle_touch_conversions`, `last_touch_conversions`). Outputs per content piece:
- Total sessions
- Engaged sessions (sessions meeting the engagement threshold)
- Conversions where this content was the first touch
- Conversions where this content was a touch in the path
- Influence score (composite of presence in conversion paths)
### Step 4 — Visualize content influence
The question the chart needs to answer: **which content pieces show up most often in conversion paths, even when they're not the last touch?**
A bar chart of "conversions influenced" (presence in conversion path) per content piece, with bars shaded by share of those that were first-touch vs middle-touch vs last-touch. Often surprising — long blog posts appear in many paths as middle-touch even when they're never the last touch.
### Step 5 — Build the attribution summary
Use `assets/content_attribution_summary.md`. The audience is typically the content team + their marketing leadership counterpart.
### Common variations
- **Time-to-conversion by content type** — does engaging with this content type accelerate the conversion timeline? Pull average days from first content engagement to conversion per content type.
- **Per-persona content paths** — if persona data is available, the same content may have very different attribution patterns per persona.
- **Repurposing signals** — if a top-converting content piece is in a single format (e.g. long blog post), surface "convert this to a webinar / podcast / video" as a recommendation.
---
### Newsletter and email content performance
**When to use:** the user runs a content-driven newsletter or email program and wants to understand which content types, topics, and formats drive the most engagement and downstream conversion.
**Platforms typically involved:** an email marketing platform (Mailchimp, Klaviyo, Brevo, HubSpot Marketing Email, Campaign Monitor, Omnisend, ActiveCampaign). CRM for downstream conversion if available. Treat open rates with care: Apple Mail Privacy Protection inflates opens, so lean on clicks and click-to-open.
### Step 1 — Pull campaign performance
> Pull the last 30-60 email campaigns from [email platform]: subject line, send date, list segment, opens, open rate, clicks, click-through rate, unsubscribes.
If the user can tag campaigns by content type (newsletter, promotional, educational, product update), pull the tag too. Otherwise, ask whether they can provide one.
### Step 2 — Pull list growth and segment data
> Pull the same period's list-growth data: new subscribers per day/week, segments they joined, source if available.
Net list growth (new subscribers − unsubscribes) is often more informative than open rates for content programs.
### Step 3 — Analyze patterns
Use `scripts/newsletter_performance.py` (columns: `campaign_name`, `send_date`, `subject_line`, `recipients`, `opens`, `clicks`, `unsubscribes`, optional `segment`, `content_type`, `conversions`, `revenue`). The script:
- Computes engagement metrics per campaign type
- Tags subject line features (length class, question, number, emoji) so you can compare open rates by pattern
- Carries the segment through so you can compare segments
- Flags campaigns with anomalously high unsubscribe rates (signal of poor content fit)
### Step 4 — Visualize the patterns
The question the chart needs to answer: **what kinds of newsletters does my audience actually engage with?**
A bar chart of open rate by content type works as a starting point. A second view: a scatter plot with subject line length on the x-axis and open rate on the y-axis, sized by send volume, colored by content type. Surfaces whether length correlates with open in this audience.
For unsubscribe analysis: a horizontal bar chart of campaigns ranked by unsubscribe rate — campaigns at the top are losing list members fastest and deserve attention.
### Step 5 — Build the review doc
Use `assets/newsletter_review.md`. The audience is the user themselves or their content team. For a monthly review, offer a live Studio dashboard (with `manage_dashboards`).
### Common variations
- **Subject line A/B testing analysis** — if the user runs A/B tests, surface which variants won and what patterns emerge.
- **Send-time analysis** — different audiences open at different times; surface the best send time by segment.
- **Content-to-conversion** — combine with CRM data: of subscribers who engaged with the newsletter regularly, what % became customers vs the non-engaged segment?
---
### Video content performance
**When to use:** the user produces video content and wants to understand cross-platform performance — what's working on YouTube vs TikTok vs Instagram Reels vs LinkedIn — and where to invest more production effort.
**Platforms typically involved:** YouTube (`YT2`) + organic social platforms (TikTok Organic `TIKBA`, Instagram Insights `IGI` via the `instagram_insights` tool, LinkedIn Pages, Pinterest Organic, X Organic, Threads Insights). For paid video: ad platforms.
### Step 1 — Pull cross-platform video data
> Pull video performance from [connected platforms] for the last 60-90 days: views, watch time, completion rate, engagement (likes/comments/shares), and follower/subscriber growth.
Each platform reports metrics differently — YouTube has average view duration and average view percentage, TikTok has average view time and completion rate, Instagram reports views and reach. Normalize as best as possible; document where direct comparison isn't possible.
### Step 2 — Pull downstream data if available
For videos with click-through (CTAs to landing pages), pull session data from GA4. For videos that drive subscribers, pull email-list-growth data if relevant.
### Step 3 — Rank by composite engagement
Use `scripts/video_content_ranker.py` (columns: `title`, `platform`, `publish_date`, `views`, `completion_rate`, `engagement_rate`, optional `clicks`, `conversions`). Composite engagement combines:
- Views (volume signal)
- Completion or retention rate (quality signal — % of viewers who finish)
- Engagement rate (likes + comments + shares / views)
- Clicks and conversions are carried through in the output but not scored
The script scores each video by percentile within its own platform (so a TikTok with 50k views isn't compared directly to a LinkedIn video with 500) and ranks videos within each platform. Compare across platforms by these within-platform scores.
### Step 4 — Visualize the portfolio
The question the chart needs to answer: **which content themes and formats are working, and where?**
A grouped bar chart with the user's top 10 videos per platform works well for platform-by-platform review. For cross-platform: a scatter plot with views on the x-axis and completion rate on the y-axis, dots colored by platform and sized by engagement.
### Step 5 — Build the performance report
Use `assets/video_content_report.md`. The output should surface:
- Which themes win across platforms (universal-appeal content)
- Which themes are platform-specific
- Which format-platform combinations are highest-leverage
- Production recommendations (length, structure, hook patterns) based on the winners
### Common variations
- **Hook analysis** — for short-form video specifically, the first 3 seconds determine retention. Pull only the top performers and surface what their hooks have in common.
- **Posting cadence vs performance** — does posting daily produce better aggregate results than posting weekly? Cross-reference posting frequency with average performance.
- **YouTube long-form vs Shorts** — separate analysis. Different audiences, different success criteria.
---
### Content gap analysis
**When to use:** the user is planning the next quarter or year of content and wants to identify topic gaps — queries the audience is searching for that the user's content doesn't address, or where competitors outrank.
**Platforms typically involved:** Google Search Console (`GW`, user's own queries) + Ahrefs (`AHRF2`) or Semrush (`SR`) for competitor keywords. Google Trends (`GT`) and Google Ads Keyword Planner (`GAKEY`) for query volume and trend.
### Step 1 — Pull the user's ranking keywords
> Pull all keywords the user's site ranks for from [Search Console / Ahrefs / Semrush]: keyword, current position, monthly search volume, current URL.
### Step 2 — Pull competitor or industry benchmark keywords
Ask the user: which 3-5 competitors should be in scope?
> Pull ranking keywords for [competitor 1, competitor 2, ...] from [Ahrefs / Semrush]. For each competitor: keyword, position, URL.
### Step 3 — Compute the gap
Use `scripts/content_gap_analyzer.py` (columns: `keyword`, `monthly_volume`, `user_position`, `competitor_position` or one `competitor_<name>_position` column per competitor, optional `search_intent`). The script keeps keywords where:
- a competitor ranks in the top 10 (`--competitor-top`)
- the user ranks below position 30 (`--user-threshold`) or not at all
- monthly volume is at least 100 (`--min-volume`)
Outputs ranked keyword gaps with: keyword, monthly volume, best competitor position, user status (position or "not ranking"), and a suggested content type from the `search_intent` column. Remove competitor brand terms yourself; the script doesn't filter them, and it doesn't use Google Trends data.
### Step 4 — Visualize the opportunity
The question the chart needs to answer: **what's the volume of search demand we're not capturing, and how concentrated is the opportunity?**
A horizontal bar chart of the top 30 gap keywords by monthly search volume works as the primary view. Color-code by suggested content type (informational, commercial, etc.) so the user can plan content programs by theme.
A secondary view: cumulative-volume curve — the top 10 gap keywords represent how much of the total gap volume? Often 70-80%, meaning a small number of content pieces can capture most of the opportunity.
### Step 5 — Build the content brief
Use `assets/content_gap_brief.md`. The output should be production-ready: each prioritized keyword should have a suggested content format (blog post, landing page, video) and a 2-sentence content angle.
### Common variations
- **Topic clustering** — instead of keyword-by-keyword, cluster the gaps into topic clusters and recommend pillar pages.
- **Quick wins** — surface keywords where the user already ranks page 2-3 but a content update could push to page 1. These are faster than net-new content.
- **Featured snippets and PAA** — if the data is available, surface queries where competitors win featured snippets or People Also Ask boxes. These are higher-leverage than position-only competitions.
---
## Ad hoc analysis
For one-off content questions outside these seven workflows ("which referral source has the highest engagement on our top blog post?", "is there a relationship between word count and bounce rate?", "which CTA variant on our pricing page is converting best?"), write fresh analysis code. The "Choosing the right visualization" framework in the SKILL.md tells you which chart family fits.
---
## A note on content metrics ladders
When the deliverable is going to a non-content audience (executives, finance), frame metrics as a ladder rather than absolute numbers: engagement (CTR, time-on-page) → consumption (downloads, video completion) → conversion (form fills, demo requests) → revenue (pipeline created, deals influenced). Different content lives at different rungs and should be measured accordingly. A blog post measured on direct revenue attribution will always look like a failure; measured on engagement and consumption, it can be the highest-leverage piece in the portfolio.
## Background
Chart choices, principles and gotchas for this area: [references/content-marketer-guide.md](references/content-marketer-guide.md).
## Before you analyze
- Load saved targets, budgets and known context with `manage_business_context` (`action: get`) and judge results against them, not generic benchmarks.
- Query correctly: follow the `marketing-data-queries` skill for discovery, field IDs and platform quirks.
- Check tracking first. If platform conversions and GA4 or backend numbers disagree by more than 20%, or spend continues with zero conversions, say so before any optimization advice.
- Pull, then analyze, as separate steps. Run one heavy query at a time.
- Evidence discipline: treat changes on fewer than ~10 conversions as noise, ignore items under 1,000 impressions, don't call learning-phase campaigns failures, check for shared budgets before budget advice, and re-pull before conceding a disputed number.
- Answer shape: conclusion, business impact, next actions, then "How I got this" (one line per data pull).
- Helper scripts in `scripts/` take a CSV and print a table. Run them if you can execute code; otherwise compute the same thing directly. Templates in `assets/` shape the final deliverable.
## After the analysis
- Analysis only recommends. If the user wants to act (pause, budget shift, negatives), use the `campaign-management` skill, with explicit approval for each change.
- For a recurring or shareable result, offer once to publish it as a live Supermetrics Studio dashboard with `manage_dashboards` (static preview first, then the live upload).
Referenced files: 15 — file references are metadata, not package contents.
wasted-spend-audit4.75 KB
View saved version →
---
name: wasted-spend-audit
description: Find wasted ad spend from live data: zero-conversion campaigns and ads, expensive CPAs, budget traps, Google and Microsoft search terms to negate, and the monthly saving. Use for "where am I wasting money", "which search terms should I exclude", "what should I pause" on Google Ads, Microsoft Advertising, Meta and other ad platforms.
---
# Wasted spend audit
## Workflows
### Search term audit and negative keywords
**When to use:** the user runs Google Ads or Microsoft Ads search campaigns and wants to find wasted spend on irrelevant queries, building a negative keyword list to upload to the platform.
**Platforms typically involved:** Google Ads (search campaigns), Microsoft Ads. This workflow doesn't apply to social platforms.
### Step 1 — Pull the search term report
> Pull the search term report from [Google Ads / Microsoft Ads] for the last 30 days, including search term, matched keyword, campaign, ad group, clicks, cost, and conversions.
Fields: Google Ads `Searchterm` (with `Keyword`, `Matchtype`), Microsoft Ads `SearchQuery`. The search term report is the granular log of actual user queries that triggered the ads — distinct from the keyword list, which is what the user bid on. Mismatch between intent and actual query is where waste lives.
### Step 2 — Audit the terms
Use `scripts/search_term_auditor.py`. The script flags queries that:
- Cost more than $X (configurable) with zero conversions
- Have CPC more than 2x the campaign average
- Match obvious irrelevance patterns (competitor brand names, "free", "jobs", "career", "wikipedia" depending on the user's industry context)
The user provides the irrelevance patterns; the script doesn't guess them. If the user doesn't have a list, suggest a starter set based on their industry and confirm.
### Step 3 — Visualize the waste
The question the chart needs to answer: **how much money are these terms costing, and which patterns are the worst?**
A horizontal bar chart of cost-per-term (top 20 worst offenders) is the most useful primary visualization. If the user has clearly grouped patterns (competitor names vs informational queries vs unrelated terms), a stacked bar chart by pattern type surfaces where the largest categories of waste live.
A pie chart or treemap of cost by pattern type works only if there are ≤5 clear categories.
### Step 4 — Build the negative keyword list
Use `assets/negative_keyword_recommendations.md`. For each proposed negative keyword, the doc includes the match type recommendation (exact / phrase / broad), the rationale (cost incurred, related queries impacted), and the campaigns where the negative should be applied.
### Step 5 — Output
Default delivery: the table as a spreadsheet ready for ad-platform upload, using the `xlsx` skill. Most ad platforms accept negative keyword bulk uploads in CSV/XLSX format. If the user prefers, deliver markdown inline.
### Common variations
- **Just one campaign** — filter to a single campaign in step 1.
- **Smaller wins** — lower `--min-cost` below its $50 default (e.g. $20).
- **Already-running negatives** — if the user provides their current negative keyword list, exclude those terms from the recommendations.
---
## Background
Chart choices, principles and gotchas for this area: [references/performance-marketer-guide.md](references/performance-marketer-guide.md).
## Before you analyze
- Load saved targets, budgets and known context with `manage_business_context` (`action: get`) and judge results against them, not generic benchmarks.
- Query correctly: follow the `marketing-data-queries` skill for discovery, field IDs and platform quirks.
- Check tracking first. If platform conversions and GA4 or backend numbers disagree by more than 20%, or spend continues with zero conversions, say so before any optimization advice.
- Pull, then analyze, as separate steps. Run one heavy query at a time.
- Evidence discipline: treat changes on fewer than ~10 conversions as noise, ignore items under 1,000 impressions, don't call learning-phase campaigns failures, check for shared budgets before budget advice, and re-pull before conceding a disputed number.
- Answer shape: conclusion, business impact, next actions, then "How I got this" (one line per data pull).
- Helper scripts in `scripts/` take a CSV and print a table. Run them if you can execute code; otherwise compute the same thing directly. Templates in `assets/` shape the final deliverable.
## After the analysis
- Analysis only recommends. If the user wants to act (pause, budget shift, negatives), use the `campaign-management` skill, with explicit approval for each change.
- For a recurring or shareable result, offer once to publish it as a live Supermetrics Studio dashboard with `manage_dashboards` (static preview first, then the live upload).
Referenced files: 5 — file references are metadata, not package contents.