Metric · Marketing

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.

TL;DR — CPC = 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_daily table with channel, campaign_name, stat_date, spend, clicks, and impressions, unioned across platforms.
  • One currency. If accounts bill in different currencies, convert during the load — mixed-currency spend makes every ratio fiction.

SQL patterns

CPC and CPM by channel by monthPostgreSQL
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;
CPC vs. CTR by campaign (competition vs. creative)PostgreSQL
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

Treating low CPC as success.→ CPC prices attention, not outcomes. Platforms can always find cheaper clicks by finding worse ones — judge the campaign on ROAS or cost per lead, and use CPC to explain the trend, not to declare victory.
Comparing CPC across channels.→ A search click carries declared intent; a feed click is interrupted scrolling. Their prices reflect different auctions selling different things. Compare CPC within a channel and audience against its own history.
Ignoring currency mixes across accounts.→ Unioning a EUR account and a USD account without conversion quietly corrupts every downstream ratio. Normalize to one currency at load time and record the rate used.
Averaging CPC across match types and placements.→ Exact-match brand terms and broad-match prospecting can differ by an order of magnitude; so can feed vs. audience-network placements. A blended average hides a mix shift as a price change — segment before you trend.

Where this metric applies

Metrics

Dashboards

FAQ

CPC vs. CPM — when does each matter?
CPC (spend ÷ clicks) prices a visit; CPM (spend ÷ impressions × 1000) prices a thousand views. Use CPC when the campaign's job is traffic and conversions, CPM when it's awareness reach — judging a reach campaign on CPC punishes it for doing its job. Under the hood most platforms bill on impressions anyway, so CPC = CPM ÷ (CTR × 10): your effective CPC is auction price divided by how clickable the ad is.
What's a good CPC?
Only your own history can say. CPC is set by auction dynamics — how many advertisers want the same audience at the same moment — so a $6 CPC on Google Ads for high-intent search can outperform a $0.50 CPC on TikTok Ads for broad awareness. Compare within a channel and audience against your own trend, and let ROAS or cost per lead settle whether the clicks were worth buying.
Why is our CPC rising?
Read it against CTR. Rising CPC with flat CTR means the auction got more expensive — more competition for your audience, often seasonal — and your ads are fine. Flat CPC with falling CTR means creative fatigue: the audience has seen the ad, stopped clicking, and the platform charges more per click as engagement drops. The two failures have different fixes (bids and audiences vs. new creative), so chart CPC and CTR per campaign together on a paid channel performance dashboard.
How do you calculate CPC and CPM?
CPC is 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?
Sync daily spend, clicks, and impressions from Google Ads, Meta Ads, and TikTok Ads into one 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.