Pulling data, formatting spreadsheets and calculating metrics by hand takes time that could go to judgment. This analysis takes a single CSV export from an ad platform and produces a campaign scorecard with ROAS rankings, funnel diagnostics, and budget recommendations.
Worked Example: Which Campaigns Meet a Spend and Return Rule?
Question: Which of three made-up campaigns meet a spend and return rule?
Inputs: Made-up rows typed by hand. Each row has a campaign name, ad spend, revenue and a count of conversions. Nothing is simulated or random, so every run gives the same result.
Method: ROAS (return on ad spend) is revenue divided by spend. CPA (cost per acquisition) is spend divided by conversions. The rule is: Scale at a ROAS of 2.0 or more, Monitor from 1.0 up to below 2.0, and Pause below 1.0. The 2.0 and 1.0 cut points are this example's rule, not a standard.
Result: North (2.50x) meets the Scale rule, East (1.25x) meets the Monitor rule, and West (0.80x) meets the Pause rule. The rows were typed so that one campaign lands in each band, which is why the output shows one of each. It is a demonstration of the rule, not a finding about real campaigns.
Limit: ROAS sets revenue against ad spend. It does not show profit, because the rows have no margin, fees or other costs.
import csv
import io
# Made-up rows typed by hand. Nothing is random, so every run is the same.
source = """campaign,spend,revenue,conversions
North,1000,2500,25
West,800,640,16
East,1200,1500,10
"""
rows = list(csv.DictReader(io.StringIO(source)))
for row in rows:
row["spend"] = float(row["spend"])
row["revenue"] = float(row["revenue"])
row["conversions"] = int(row["conversions"])
row["roas"] = row["revenue"] / row["spend"]
row["cpa"] = row["spend"] / row["conversions"]
if row["roas"] >= 2:
row["recommendation"] = "Scale"
elif row["roas"] >= 1:
row["recommendation"] = "Monitor"
else:
row["recommendation"] = "Pause"
print("Made-up rows typed by hand")
print("Input rows: 3; fields: campaign, spend, revenue, conversions")
print("Method: ROAS = revenue / spend; CPA = spend / conversions")
print("Rule: ROAS >= 2.0 Scale; >= 1.0 and < 2.0 Monitor; < 1.0 Pause")
print("campaign | spend | revenue | conversions | ROAS | CPA | recommendation")
for row in sorted(rows, key=lambda item: item["roas"], reverse=True):
print(
f"{row['campaign']} | ${row['spend']:.2f} | ${row['revenue']:.2f} | "
f"{row['conversions']} | {row['roas']:.2f}x | ${row['cpa']:.2f} | "
f"{row['recommendation']}"
)
Printed output of that script:
Made-up rows typed by hand
Input rows: 3; fields: campaign, spend, revenue, conversions
Method: ROAS = revenue / spend; CPA = spend / conversions
Rule: ROAS >= 2.0 Scale; >= 1.0 and < 2.0 Monitor; < 1.0 Pause
campaign | spend | revenue | conversions | ROAS | CPA | recommendation
North | $1000.00 | $2500.00 | 25 | 2.50x | $40.00 | Scale
East | $1200.00 | $1500.00 | 10 | 1.25x | $120.00 | Monitor
West | $800.00 | $640.00 | 16 | 0.80x | $50.00 | Pause
The Reporting Problem Agencies Know Too Well
Every month, the same cycle repeats. Export CSV from Google Ads. Export from Meta Ads Manager. Maybe another from TikTok or LinkedIn. Open Excel. Calculate ROAS manually (revenue divided by spend). Build charts. Copy into a Google Slides deck. Repeat for every client. Some agencies use tools to automate the data pull, but the analysis and visualization are still manual. And the output is mostly descriptive: it states a ROAS for each campaign. That tells the client what happened. It does not tell them what to do.
To test whether your own outcome differs between groups, and which groups differ, try the free group comparison tool.
Reports that include prescriptive recommendations ("pause Campaign D, reallocate budget to Campaign A") give clients something to act on, instead of only descriptive metrics.
What This Analysis Produces
The report may show the parts below, each answering a specific question:
- ROAS by Campaign: bar chart showing return on ad spend for every campaign, sorted highest to lowest. You immediately see which campaigns are printing money and which are underwater. A horizontal reference line marks your ROAS target.
- ROAS by Channel: aggregated to the channel level (Facebook, Google Search, influencer, etc.). Answers the strategic question: which channels deserve more budget overall?
- Funnel Efficiency: CTR (impressions to clicks), lead rate (clicks to leads), and conversion rate (leads to sales) broken out by channel. This is how you diagnose why a campaign has low ROAS. A high CTR with a low conversion rate may point to the wrong audience. A low CTR with a high conversion rate may point to creative that needs work.
- Spend vs. Revenue Scatter: each campaign plotted with spend on the x-axis and revenue on the y-axis. Dots above the 1.0x ROAS line show revenue above ad spend. This alone does not show profit, which also depends on margin and other costs. The chart can also hint at diminishing returns: if high-spend campaigns sit closer to the 1.0x line, efficiency may be falling as spend rises.
- Campaign Scorecard Table: every metric for every campaign: spend, revenue, ROAS, CPA, CTR, conversion rate. The reference table you bring to the client meeting.
- Budget Recommendations: each campaign classified by tier, such as Scale (increase budget), Monitor (adequate performance) or Pause (underperforming, investigate).
- Trend Analysis, if your data includes a date column, shows whether each campaign's efficiency is improving or degrading over time.
- Executive Summary: key findings condensed into short bullet points that can be copied into a message or email to the client.
From Numbers to Recommendations
A scorecard that ends in a recommendation gives the client something to act on, as the worked example does: a rule turns each campaign's ROAS into Scale, Monitor or Pause. Time not spent on manual reporting could go to deeper analysis, such as a stats test to see whether a gap between search and social could be due to chance. That test needs a sound study plan and like-for-like outcome data.
What Data You Need
A CSV export of campaign performance data from any ad platform. Required columns:
- Campaign name: identifier for each campaign
- Spend: amount spent on each campaign
- Revenue: revenue or conversion value generated
Optional columns for richer analysis:
- Channel: Facebook, Google Search, TikTok, etc. Enables cross-platform comparison.
- Impressions: enables CTR calculation
- Clicks: enables click-through and lead rate analysis
- Leads/conversions: enables full funnel breakdown
- Date: enables trend analysis over time
Export this from Facebook Ads Manager, Google Ads, your analytics platform, or even a spreadsheet where you track spend manually. Each row should represent one campaign's performance for a time period. More campaigns and more time periods give the comparison more to work with.
Common Pitfalls the Report Helps You Avoid
Optimizing for ROAS Without Considering Scale
Campaign A has 8x ROAS on $5,000 spend ($40,000 revenue). Campaign B has 3x ROAS on $100,000 spend ($300,000 revenue). Killing Campaign B because its ROAS is "only" 3x would cost $300,000 in revenue. A rule based on ROAS alone would miss this, so look at revenue contribution as well.
Ignoring Funnel Position
Brand search campaigns often show high ROAS. Those customers were already looking for you. Upper-funnel campaigns like display or awareness often show low ROAS on a last-click basis because they introduce new customers who convert through a different channel later. The funnel efficiency chart makes this visible.
Over-Scaling Winners
The spend vs. revenue scatter plot reveals diminishing returns. If a campaign's ROAS drops as spend increases, there is an inflection point beyond which additional budget yields diminishing returns. The chart can help you avoid the mistake of "this campaign has great ROAS, let's 5x the budget" only to watch efficiency collapse as the audience saturates.
The Monthly Workflow
Here is one way a paid media agency could fit this into a monthly cycle. At month-end, the account manager exports campaign performance from each platform (Google Ads, Meta, TikTok) and combines them into a single CSV per client. They upload to MCP Analytics and run the ROAS efficiency analysis. They get a campaign scorecard with tier recommendations.
The account manager reviews the automated recommendations and adds strategic commentary: context the analysis cannot know, like "Campaign B is a brand awareness campaign so low ROAS is expected and acceptable" or "Client is launching a new product line in Q2, so prospecting spend will increase." They share the interactive report with the client or download the PDF for the monthly retainer deliverable. The client can drill into individual campaigns in the interactive view. The prescriptive recommendations (scale this, pause that, reallocate here) give the client meeting a clear agenda instead of a walkthrough of flat metrics.
When to Use Something Else
- Need to compare just two campaigns with statistical rigor: Use a t-test to see whether the difference could be due to chance.
- Want to benchmark one client against your whole portfolio: Use cross-client benchmarking to compare performance across all your clients.
- Need to understand cross-channel attribution: ROAS analysis treats each campaign independently. For understanding how channels influence each other over time, you need multi-touch attribution or media mix modeling.
Your turn
Bring your own data and the question you actually need answered.
MCP AnalyticsData science by email Send us your data and your question, and we will reply. ds@mcpanalytics.ai