# Find Your Amazon DSP Frequency Cap in AMC

Canonical page: https://www.kuudo.com/guides/amc-optimal-frequency-cap/

Find your Amazon DSP frequency cap in AMC: bucket users by daily impressions, then compare cumulative return with cumulative cost before choosing a cap.

Author: Thomas Spicer
Updated: Oct 19, 2026

## Summary

Purchase rate by frequency bucket leaves cost out, so it cannot set a cap on its own. Amazon's Optimal Frequency Analysis playbook buckets users by daily impressions, computes cumulative cost % and cumulative return %, and sets the cap at the last bucket where the change in their difference (Percent Change) is still above zero. In the playbook's worked example that is a daily cap of 4. In a second example, a cap of 9 instead of 5 dropped cumulative ROAS from 1.17 to 0.95.

Your Amazon DSP (demand-side platform) frequency cap is the last bucket where cumulative return still grows faster than cumulative cost, not the bucket with the best purchase rate. Amazon's Optimal Frequency Analysis playbook finds it in Amazon Marketing Cloud (AMC) by bucketing users by daily impressions. Its worked example lands on a daily cap of 4.

The agent runs that method in your [Amazon Marketing Cloud](/features/amc/) (AMC) instance through the [Amazon Ads MCP](/features/amazon-ads-mcp/), joins `amazon_attributed_events_by_traffic_time` conversions to the impression buckets, and checks each step against Amazon's own guidance in [Amazon Agent Atlas](/features/agent-atlas/). The [Amazon Marketing Cloud Skill](/features/skills/amazon-ads/marketing-cloud/) carries the AMC SQL rules. You get one number and the table behind it.

The question usually arrives in one line:

> *"What's our optimal DSP frequency cap, and at what impression count are we paying for ad fatigue instead of conversions?"*

It is easy to answer wrong, because the rate column is the first thing anyone plots. So the instruction to [the agent](/features/ai-clients/) is plain: skip the rate column, run the cumulative cost-and-return method, and show where it crosses.

[ChatGPT, Claude, Perplexity, Microsoft Copilot, and whatever comes next](/features/ai-clients/) know nothing about your business out of the box, and your competitors use them too. Kuudo gives those same tools your edge:

- **Your account, as it is right now.** The Amazon Ads MCP runs the query in your authorized AMC instance.
- **Your judgment, running every time.** [Skills](/features/skills/) preserve the rules your team expects, and Atlas supplies Amazon-specific guidance.
- **Your call, before anything changes.** Approval controls keep activation and other consequential changes with you.

## The Amazon Ads MCP buckets every user by daily impression count, not by one average

The raw shape every later step reads from is a per-bucket table, not a single average frequency. The Amazon Ads MCP runs the bucketing query in AMC, and the agent checks it against the **Amazon DSP and sponsored ads impression frequency and conversions** query that Atlas retrieves. That query groups users into `frequency_01` through `frequency_25+`, where `25+` means 25 or more exposures, and reports users, impressions and purchases per bucket.

The query below follows the same pattern for DSP alone, at the day grain Amazon's playbook uses, because the cap you set is a daily one. Each row counts one user on one day. Conversions come from `amazon_attributed_events_by_traffic_time`, filtered to the same campaigns so sponsored ads conversions do not land in DSP buckets.

Three details come from Amazon's AMC documentation. `total_cost` is in millicents, so the query divides by 100,000. AMC does not support `ORDER BY` in a query, so you sort the downloaded output. The date range is set on the run, not in the SQL. The block is unvalidated, so run it in an AMC instance with DSP data before you trust it.

<!-- amc-sql: skip — DSP-sourced frequency pull; validate in an AMC instance with DSP data. Pattern: Amazon's DSP and sponsored ads impression frequency and conversions instructional query -->
```sql
-- UPDATE: replace with your Amazon DSP campaign IDs
WITH campaign_ids (campaign_id) AS (
  VALUES
    (111111111111)
),
impressions AS (
  SELECT user_id,
         impression_date           AS event_date,
         SUM(impressions)          AS impressions,
         SUM(total_cost) / 100000  AS cost  -- total_cost is in millicents
  FROM dsp_impressions
  WHERE campaign_id IN (SELECT campaign_id FROM campaign_ids)
    AND user_id IS NOT NULL
  GROUP BY 1, 2
),
conversions AS (
  SELECT user_id,
         traffic_event_date       AS event_date,
         SUM(purchases)           AS purchases,
         SUM(total_product_sales) AS product_sales
  FROM amazon_attributed_events_by_traffic_time
  WHERE campaign_id IN (SELECT campaign_id FROM campaign_ids)
  GROUP BY 1, 2
),
by_user_day AS (
  SELECT i.user_id,
         i.impressions,
         i.cost,
         LEAST(i.impressions, 25)     AS frequency,
         COALESCE(c.purchases, 0)     AS purchases,
         COALESCE(c.product_sales, 0) AS product_sales
  FROM impressions i
  LEFT JOIN conversions c
    ON c.user_id = i.user_id
   AND c.event_date = i.event_date
)
SELECT CONCAT(FORMAT('frequency_%02d', frequency),
              IF(frequency = 25, '+', '')) AS frequency_bucket,
       COUNT(user_id)     AS user_days_in_bucket,
       SUM(impressions)   AS impressions_in_bucket,
       SUM(cost)          AS cost,
       SUM(purchases)     AS purchases,
       SUM(product_sales) AS product_sales
FROM by_user_day
GROUP BY 1
```

> **The AI is shared. The moat is yours.**
> - **Your account, as it is right now.** The shared AI can't query your AMC instance, so it can't build a single frequency bucket. You'd have to export and paste a table into a chat history you don't control. The Amazon Ads MCP runs the query inside AMC, and only aggregated results come back.
> - **Your judgment, running every time.** Ask the shared AI how to bucket and it may guess a table or a column. A wrong column fails the run; a wrong table, such as a segment table that repeats each impression once per audience segment, returns inflated counts. The agent reads the real schema first.

## Purchase rate by bucket can't set the cap, because it leaves out cost

Purchase rate rises across the first buckets in Amazon's frequency query example: 0.48% at one impression, 1.10% at two, 3.86% at three. Other Amazon examples show the rate flattening after seven exposures, or spiking at three and then falling. None of those shapes says what the added impressions cost, so the rate column alone cannot tell you where to stop.

The agent flags that before it names a cap, rather than chasing the best-looking number. Atlas also carries Amazon's warning from the same query: the optimal frequency it finds for your chosen KPI may not be optimal across all of your advertising channels.

> **The AI is shared. The moat is yours.**
> - **Your judgment, running every time.** Ask the shared AI "which frequency converts best?" and it points at the top of the rate curve. That answer ignores cost, which is how you keep paying for fatigue. The agent puts the cost side next to the rate before it names a cap.
> - **Your account, as it is right now.** Even if you spot the trap, the shared AI has no cost per bucket from your campaigns and no way to run the cumulative math on them. The Amazon Ads MCP has both, over your real campaign window.

## The agent sets the cap at the last bucket where Percent Change is still above zero

The agent runs **Optimal Frequency Analysis in Amazon Marketing Cloud** the way Amazon's playbook lays it out, and the result is the analysis report you get. Per bucket it computes:

- **Cumulative cost and cumulative return:** each bucket's total plus every bucket before it. Return is the KPI you choose, such as purchases or sales.
- **Cumulative cost % and cumulative return %:** each cumulative total divided by the total across all buckets.
- **Percent Difference:** cumulative return % minus cumulative cost %.
- **Percent Change:** this bucket's Percent Difference minus the prior bucket's.

The cap is the last bucket where Percent Change is above zero. Past it, the added cost grows faster than the added return. Here is the playbook's worked example, measured daily over 90 days with conversions as the return:

| frequency_bucket | conversions | cumul. conversions | cost | cumul. cost | cumul. conversions % | cumul. cost % | Pct Difference | Pct Change |
|---|---|---|---|---|---|---|---|---|
| 1 | 9,203 | 9,203 | $7,801 | $7,801 | 19% | 9% | 9.90% | n/a |
| 2 | 6,532 | 15,735 | $7,933 | $15,734 | 32% | 18% | 14.18% | 4.28% |
| 3 | 5,024 | 20,759 | $7,492 | $23,226 | 43% | 27% | 15.87% | 1.69% |
| 4 | 4,157 | 24,916 | $7,060 | $30,286 | 51% | 35% | 16.28% | 0.41% (last >0) |
| 5 | 3,569 | 28,485 | $6,621 | $36,907 | 58% | 42% | 15.99% | -0.29% (crosses) |

Bucket 5's -0.29% is the first negative, so the playbook sets a daily frequency cap of 4. A second example in the playbook shows what a loose cap costs. Optimizing one line item on total sales over a month, the model recommends a cap of 5, where cumulative return on ad spend (ROAS) is about 1.17. A cap of 9 drops it to 0.95, where spend exceeds sales.

The playbook also fits a curve and takes derivatives, but for a different job: finding a minimum frequency for under-served audiences and the apex of the curve. The cap itself comes from the Percent Change zero-crossing.

> **The AI is shared. The moat is yours.**
> - **Your judgment, running every time.** The shared AI may never have seen this playbook and guesses a round number like "cap at 3." The agent runs the playbook's cumulative bookkeeping, and every column in the table can be checked.
> - **Your account, as it is right now.** The method needs per-bucket cost and conversion volume from your real campaign window. The shared AI can't query it; the Amazon Ads MCP runs it, and the same query reproduces the table.

## Atlas grounds the warning that your high-frequency tail is too thin to trust

High-frequency buckets thin out fast. In the example in Amazon's **Reach and impression frequency** query, around 90% of users saw the ad three or fewer times; in the frequency and conversions example, each bucket after nine holds under 1% of users. AMC also drops rows below its minimum distinct-user count by default. Read the cap off where the data is dense, not off a noisy tail.

Atlas carries those caveats from Amazon's queries, and the agent checks your run against the playbook's prerequisites:

- An AMC instance with at least 7 days of backfilled data.
- At least 4 active campaigns.
- A wait of about two weeks after the campaign ends, so the 14-day attribution window can close.

Amazon also notes that optimal frequency is not one size fits all. It depends on the campaign goal (brand awareness versus conversion), campaign length, audience size, whether it is a new product launch, and the type of product.

> **The AI is shared. The moat is yours.**
> - **Your judgment, running every time.** The shared AI may compute a cap off your `frequency_18` bucket as if it were solid, never warning that the tail may hold a handful of users, or that AMC filters out rows below its threshold. The agent reads the cap off the dense buckets.
> - **Your account, as it is right now.** The shared AI can't see that your campaign ran only 5 days or has 2 active campaigns, below the playbook's 7-day, 4-campaign floor, so it can't tell you the answer isn't ready yet. The Amazon Ads MCP can check the campaigns and dates in your account.

## What happens next: set the cap in Amazon DSP and re-measure monthly

The artifact is a decision: one cap, with its time unit. From there:

- **Set it in Amazon DSP.** Put it on the campaign or the ad group (formerly the line item) as a maximum number of impressions over a number of days or hours. Frequency groups share one cap across campaigns.
- **Apply it with approval.** The Amazon Ads MCP includes the DSP campaign and ad group update operations, so the agent can prepare the change. Depending on your workspace policy, it may require approval before it goes live.
- **Re-measure monthly.** Amazon's playbook recommends it, and the Amazon Ads MCP can schedule the AMC workflow so each run lands a fresh table for review. The [Amazon Marketing Cloud Skill](/features/skills/amazon-ads/marketing-cloud/) keeps the SQL rules the same on every run.
- **Or take Amazon's no-SQL route.** The point-and-click Optimal Frequency solution in AMC recommends a daily cap range and can apply it across campaigns. The SQL path shows every step of the math and takes any KPI or breakout you choose.

The AMC run itself stays inside AMC. For the questions around it, the [Amazon Agent Data layer](/features/amazon-agent-flow/), built on Amazon Agent Flow, lands your Amazon Ads and Selling Partner data in a lake you own. An agent can then set DSP spend beside the sales and inventory the [Amazon Selling Partner MCP](/features/amazon-selling-partner-mcp/) reads.

A frequency cap is one number, but it only means anything when it sits on the cost side of the math instead of the rate side. Set it there and you stop paying for impressions past the point where added cost outgrows added return.

*Next in the series: where that capped DSP impression actually sits in the full conversion path, mapped end to end in [the path-to-conversion Sankey](/guides/amc-path-to-conversion-sankey/).*


## Frequently asked questions

### What's the optimal DSP frequency cap and how do I find it?

Not from the highest-converting bucket, because purchase rate leaves cost out. Amazon's Optimal Frequency Analysis playbook buckets users by daily impressions, computes cumulative cost % and cumulative return %, and sets the cap at the last bucket where the change in their difference (Percent Change) is still above zero.

### Why is my best-converting frequency bucket the wrong cap?

Purchase rate by bucket ignores what each added impression costs, and a thin high-frequency bucket can spike on a handful of users. Amazon's own examples show the rate climbing, flattening, or peaking and falling. The cost-side method asks a different question: does the next bucket add more cumulative return than cumulative cost?

### What is the Percent Change column in AMC optimal frequency analysis?

Percent Difference is cumulative return % minus cumulative cost % at each bucket. Percent Change is that difference minus the prior bucket's. The recommended cap is the last bucket where Percent Change is above zero. In the playbook's worked example it turns negative at bucket 5, so the daily cap is 4.

### Why are my high-frequency buckets empty or missing in AMC?

Few users reach them: in the example in Amazon's Reach and impression frequency query, around 90% of users saw the ad three or fewer times. AMC also filters out rows below its minimum distinct-user count by default. Read the cap off the dense low-frequency buckets, and confirm the playbook's prerequisites: at least 7 days of backfilled data and 4 active campaigns.

### Why does my AMC frequency query fail or return no rows?

Check three things. AMC does not support ORDER BY in a query, so remove it and sort the downloaded output. Rows below AMC's minimum distinct-user count are filtered out by default, so a narrow campaign set or a short window can return few rows; widen the window. And total_cost is in millicents, so divide by 100,000 before comparing cost with sales.

### Which AMC table has the conversions for frequency analysis?

amazon_attributed_events_by_traffic_time carries the attributed purchases and product sales you join to your impression buckets. The impression and cost side comes from dsp_impressions. Amazon's frequency query also reads sponsored_ads_traffic when you want sponsored ads impressions in the count.

### Where do I actually set the frequency cap once I have the number?

In Amazon DSP, on the campaign or the ad group (formerly the line item), as a maximum number of impressions over a number of days or hours. Frequency groups share one cap across campaigns. Amazon's point-and-click Optimal Frequency solution in AMC recommends a daily cap range and can apply it without SQL; the SQL path shows every step of the math.


## Sources

- [Optimal frequency analysis playbook (Amazon Ads)](https://advertising.amazon.com/API/docs/en-us/guides/amazon-marketing-cloud/playbooks/optimal-frequency-analysis)

- [Optimal Frequency solution in Amazon Marketing Cloud (Amazon Ads)](https://advertising.amazon.com/resources/whats-new/optimal-frequency)

- [Amazon DSP impressions table in AMC (Amazon Ads)](https://advertising.amazon.com/API/docs/en-us/guides/amazon-marketing-cloud/datasources/dsp_impressions)

- [AMC SQL limitations and unsupported functions (Amazon Ads)](https://advertising.amazon.com/API/docs/en-us/guides/amazon-marketing-cloud/amc-sql/limitations)

