What is a good CPM?
One that buys impressions from people who go on to convert, at a total cost you can afford.
The two things that move it most are the audience you are bidding for, because advertisers compete harder for some people than others, and the time of year, because they all compete hardest in the same few weeks. A low CPM is only a price. Paying very little to show an ad to the wrong people is still money gone.
How it's calculated
CPM = (ad spend ÷ impressions) × 1,000
It is the cost of a thousand impressions, and the platform usually reports it for you. The CPM formula page has the Google Sheets version and a worked example.
Published benchmarks
CPM benchmarks are published by ad tech vendors and agencies from the accounts they can see; the platforms publish none. The two sources below disagree with each other by about two to one on the same platforms, which tells you how much the panel decides the figure. Both are US dollars.
| Context | Reported CPM | Source |
|---|---|---|
| Meta Ads, all advertisers in the panel | $7.34 average, 2024 | Gupta Media, State of Social Media CPM Report, 2024 |
| Meta Ads, DTC ecommerce brands | $14.19 median, 2025 | Triple Whale, Ecommerce Benchmarks, 2025 |
| TikTok Ads, all advertisers in the panel | $4.27 average, 2024 | Gupta Media, State of Social Media CPM Report, 2024 |
| TikTok Ads, DTC ecommerce brands | $13.26 median, 2025 | Triple Whale, Ecommerce Benchmarks, 2025 |
| YouTube, all formats | $3.83 average, 2024 | Gupta Media, State of Social Media CPM Report, 2024 |
Gupta Media's figure is the average across tens of billions of impressions bought through its own agency, across every objective; Triple Whale's is a median across the ecommerce brands on its platform, which buy conversions rather than reach and pay more per thousand for it. There is no row for Google Display because nobody with a large panel publishes one and Google does not either; the figures that circulate for it are agency estimates with no stated sample. YouTube's row is all of Gupta's YouTube buying, not skippable in-stream on its own, which no large panel reports separately.
Why benchmarks mislead
It is a price for the wrong thing. CPM measures what an impression costs, and nobody buys impressions for their own sake. Two campaigns with the same CPM can have cost per conversion figures a long way apart, because one reached buyers and the other reached scrollers.
Audience and country set the price. People who recently searched for mortgages cost more to reach than people who like videos of dogs, and a thousand impressions in one country costs a multiple of a thousand in another. A benchmark averaged across them is a number for nobody.
A full-screen vertical video and a small banner in a feed are both impressions. They are not the same product.
Platforms disagree on what an impression is. Some count an ad as seen when it is served, others only when a set share of it has been on screen for a set time. The same campaign has two CPMs depending on the definition.
The run-up to peak shopping periods pushes every auction up, so a benchmark from one quarter and your figure from another are not comparing like with like.
The advertisers in the sample are the ones who kept bidding at those prices.
Find your own baseline
Compute your own CPM over the last quarter from total spend and total impressions, never by averaging the CPM of each campaign. With spend in column B and impressions in column C:
=IF(SUM(C2:C13)=0, "", SUM(B2:B13)/SUM(C2:C13)*1000)
Then put it next to the number that matters. Cost per conversion is the CPM divided by a thousand, then divided by the click-through rate, then divided by the conversion rate. As an illustration with made-up numbers: a CPM of £8.00, a click-through rate of 1% and a conversion rate of 2% gives £0.008 ÷ (0.01 × 0.02), which is £40.00 per conversion. Halve the CPM and the cost per conversion halves. Halve the click-through rate and it doubles. Your baseline is the CPM at which that final figure is one you can live with. The CPA formula page has the forward version of the sum.
Keeping it current
A scheduled Fresh Sheets report can keep Amount spent and Impressions by campaign from Meta Ads in their own tab, so the baseline always covers the last 90 days rather than whenever someone last exported it.
Fresh Sheets replaces that tab's contents on every refresh, so keep your formulas on a separate tab. This version finds each column by its heading, so it still works if a field is added and the columns move:
=SUM(INDEX('Meta Ads'!A:Z, 0, MATCH("Amount spent", 'Meta Ads'!1:1, 0))) / SUM(INDEX('Meta Ads'!A:Z, 0, MATCH("Impressions", 'Meta Ads'!1:1, 0))) * 1000