What are CPC and CPM, and how do you measure them in Metabase?
CPC — cost per click — is spend divided by clicks; its siblingCPM is spend divided by impressions, times 1,000. Together they price attention: what a visit costs and what a thousand views cost. They say nothing about outcomes — that's ROAS and cost per lead — but they're the earliest signal that a campaign's economics are shifting. Measure them in Metabase from daily data synced from Google Ads, Meta Ads, and TikTok Ads.
spend ÷ clicks, CPM = spend ÷ impressions × 1000. Both price attention, not outcomes, and both are set by auction competition — so compare within a channel and audience, never across channels.What CPC and CPM measure
CPC measures the market price of a click on your ad, which is mostly a function of who else is bidding on the same audience and how relevant the platform thinks your ad is. CPM measures the raw price of inventory, which makes it the right lens for awareness buying, where clicks aren't the point. Neither is a success metric: a cheap click that doesn't convert costs more than an expensive one that does. Their job is diagnostic — they move days or weeks before conversion metrics do.
Reading CPC with CTR
CPC alone is ambiguous; paired with CTR, it separates the two forces that drive it. Rising CPC with flat CTR is auction pressure: competitors moved in, and the fix lives in bids, audiences, and dayparting. Flat CPC with falling CTR is creative fatigue: the audience tuned out, effective CPC is about to climb, and the fix is new creative. The same chart, read quarterly, also catches seasonal auction inflation before it gets misdiagnosed as a campaign problem.
What data does it need?
- An
ad_performance_dailytable withchannel,campaign_name,stat_date,spend,clicks, andimpressions, unioned across platforms. - One currency. If accounts bill in different currencies, convert during the load — mixed-currency spend makes every ratio fiction.
SQL patterns
SELECT
channel,
date_trunc('month', stat_date) AS month,
SUM(spend) AS spend,
SUM(clicks) AS clicks,
SUM(impressions) AS impressions,
ROUND(SUM(spend) / NULLIF(SUM(clicks), 0), 2) AS cpc,
ROUND(SUM(spend) * 1000.0 / NULLIF(SUM(impressions), 0), 2) AS cpm
FROM ad_performance_daily
WHERE stat_date >= CURRENT_DATE - INTERVAL '12 months'
GROUP BY 1, 2
ORDER BY 2, 1;SELECT
campaign_name,
date_trunc('month', stat_date) AS month,
ROUND(SUM(spend) / NULLIF(SUM(clicks), 0), 2) AS cpc,
ROUND(
100.0 * SUM(clicks) / NULLIF(SUM(impressions), 0),
2
) AS ctr_pct
FROM ad_performance_daily
WHERE stat_date >= CURRENT_DATE - INTERVAL '180 days'
GROUP BY 1, 2
ORDER BY 1, 2;Pitfalls
Where this metric applies
- Google Ads + Metabase — CPC by campaign, match type, and network
- Meta Ads + Metabase — CPC and CPM by ad set and placement
- TikTok Ads + Metabase — auction CPM and click costs by campaign
Related
Metrics
Dashboards
FAQ
CPC vs. CPM — when does each matter?
What's a good CPC?
Why is our CPC rising?
How do you calculate CPC and CPM?
SUM(spend) / SUM(clicks); CPM is SUM(spend) * 1000 / SUM(impressions) — both from the same daily performance rows, with NULLIF guarding zero denominators. Compute them from summed spend and clicks rather than averaging daily CPC values, since averaging ratios weights a 10-click day the same as a 10,000-click day.How do you track CPC in Metabase?
ad_performance_daily table, converting currencies during the load if accounts bill differently. Chart CPC and CPM by channel and month, add the per-campaign CPC vs. CTR view, and pin both next to ad spend pacing so price and budget burn read together.