Run everything you never had time to implement. Define your process once, and keep it running with Qore.

All reports
Amazon Ads Console
Advertising Performance

Amazon Sponsored Products Campaign Placement Report

The Sponsored Products campaign placement report is the campaign report cut by where the ad was shown — one row per campaign per placement per day, with spend, impressions, clicks and the attributed purchases, units and sales behind them at 1, 7, 14 and 30 day windows. It answers the question the campaign report cannot, which is whether Top of Search, product detail pages or everything else is where the money went and where the sales came back from.

Known upstream as
spCampaigns
One row is
One row per placement
Refreshed
Daily
Columns
44
Marketplaces
All marketplaces
History
Amazon retains 95 days of spCampaigns data and caps a single report request at a 31-day date range, so a longer history has to be accumulated by pulling repeatedly and keeping what you pulled. The Ads console's own Placement report, which is this same data exported from the console rather than a report type of its own, documents a 90-day lookback instead.
Latency
Amazon publishes initial impression and click data within about 12 hours and initial conversion data within 24 hours, so a day is readable the next morning but not final. Clicks are then adjusted by traffic validation — Amazon monitors for up to 30 days and suggests waiting 5 days before judging click data — and conversions are restated 1, 7 and 28 days after the event and stay subject to change up to 60 days back. The rows also carry attribution windows up to 30 days, so a recent day's purchases and sales keep moving either way.
Requires
Amazon Ads API access

What this report contains

One row per campaign, per placement, per day, for Sponsored Products. It is the campaign report's roll-up cut once more by where on Amazon the ad was shown: the same 43 columns plus placement_classification, and (campaign_id, placement_classification, date) was unique on every one of 36,108 rows across 14 production files.

placement_classification is a label, not a code. Four values have been seen in production, carried exactly as Amazon spells them: Detail Page on-Amazon, Other on-Amazon, Top of Search on-Amazon and Off Amazon. Detail Page and Other were the bulk of the rows in that sample, Top of Search about a quarter, and Off Amazon the smallest slice.

The rest of the row falls into three groups. The campaign_* columns are configuration — status, bidding strategy, budget, budget type and currency, and the rule-based budget that may have overridden it. They describe the campaign, not the placement, so they repeat identically across a campaign's three or four rows for the day. impressions, clicks, click_through_rate, cost, spend and cost_per_click are what the placement cost you. Everything after that is what Amazon attributed back, repeated four times for the 1, 7, 14 and 30 day windows, and repeated again for units and for same-SKU. The windows nest — purchases_30d includes purchases_7d — so picking one is choosing how long a click gets credit, not choosing a different measure.

How to get it

Through the Amazon Ads API v3, POST a report request to /reporting/reports with reportTypeId: spCampaigns, adProduct: SPONSORED_PRODUCTS, timeUnit: DAILY, format: GZIP_JSON and — the part that makes it this report rather than the campaign report — groupBy: ["campaign", "campaignPlacement"]. List every column you want in columns. Poll the report ID until it completes and download the gzipped file, which is a top-level JSON array of flat objects whose keys are exactly the columns you asked for.

Two traps. The v3 API returns the requested column set and nothing else, so a column missing from the file is missing from your request, not from Amazon's schema. And the grouping is the whole difference: the same reportTypeId with groupBy: ["campaign"] is the campaign report, and the column list is otherwise identical apart from placement_classification, so a pipeline that keys files on report type alone will mix the two.

In the Amazon Ads console, the same data is the Placement report: Measurement & Reporting in the sidebar, then Sponsored ads reports, then Create report, choosing Sponsored Products and the placement report at a summary or daily time unit. Amazon is retiring that section — unified reporting at Measurement and Reporting → Reporting went generally available in June 2026, and Sponsored Ads reports is being sunset by 31 December 2026 — so the API request above is the durable path. There is no separate Sponsored Products placement report type in the API; the campaignPlacement grouping of the campaign report is it.

Reports are per profile, so a seller in several marketplaces gets one file per marketplace, each in that marketplace's currency — campaign_budget_currency_code agreed with the credential's marketplace on every row checked.

Sample rows

Illustrative values, not data from a real account. Shown to give the shape of the file.

datecampaign_nameplacement_classificationimpressionsclicksclick_through_ratecostpurchases_7dsales_7d
2026-09-14Brand Defense - ExactTop of Search on-Amazon124803742.997411.40411639.59
2026-09-14Brand Defense - ExactDetail Page on-Amazon256102050.800143.5012419.88
2026-09-14Brand Defense - ExactOther on-Amazon301151510.50190.607244.93
2026-09-14Brand Defense - ExactOff Amazon4020180.4489.9000.00
2026-09-14Category Targeting - AutoTop of Search on-Amazon89001872.101205.7015449.85

Field reference

ColumnTypeDescription
datedateThe advertising day the row's metrics are attributed to, as ISO YYYY-MM-DD with no time component and no timezone offset — on all 36,108 rows checked. This is the column the file is partitioned on.
campaign_idstringAmazon's campaign identifier. Arrives as a 12 to 15 digit JSON number and is carried as a string because it is a join key, and a numeric type would silently drop a leading zero.
campaign_namestringThe campaign's name, for reading. Join on campaign_id, not on this.
campaign_statusstringThe campaign's status as Amazon reports it. A campaign-level setting, so it repeats identically on each of the campaign's placement rows for the day.
campaign_bidding_strategystringThe campaign's bidding strategy. Campaign-level, so identical across the campaign's placement rows; a change here is the first thing to check when cost_per_click steps.
campaign_budget_amountdecimalThe campaign's configured budget, repeated on every placement row of the campaign. It is a campaign-level number, not a per-placement one, so summing it across a campaign's placement rows counts the budget three or four times.
campaign_budget_typestringThe kind of budget campaign_budget_amount is — daily or lifetime.
campaign_budget_currency_codestringThe currency of campaign_budget_amount. Populated on every row, and it agreed with the credential's marketplace across the validation sample (AED, AUD, CAD, EUR, GBP, INR, MXN, SEK, USD). The row's money columns were in the same currency in every file checked; the name says which meaning is which if that ever stops being true.
campaign_rule_based_budget_amountdecimalThe budget in force when a budget rule overrode the configured amount. Null on every one of the 36,108 rows in the validation sample — no advertiser in it used rule-based budgets — but present on every file, and populated in the sibling campaign report's sample, so expect it to fill in when a rule applies.
campaign_applicable_budget_rule_idstringIdentifier of the budget rule that applied, if any. Null throughout the validation sample, for the same reason.
campaign_applicable_budget_rule_namestringName of the applied budget rule, if any. Null throughout the validation sample.
placement_classificationstringWhere the ad was shown. The column that turns the campaign report into this one — (campaign_id, placement_classification, date) is unique on every row checked. Never null, and a human-readable label rather than an enum code, carried verbatim with Amazon's spelling. The four values seen in production are Detail Page on-Amazon, Other on-Amazon, Top of Search on-Amazon and Off Amazon.
impressionsint64Times an ad from this campaign was displayed in this placement on this day.
clicksint64Clicks on those impressions.
click_through_ratefloat64Clicks divided by impressions, as a percentage rather than a 0 to 1 fraction — it reaches 100.0. Null where there were no impressions, which was 3.8% of rows in the sample. Computed per row, so recompute from the counts when aggregating instead of averaging the column.
costdecimalWhat the clicks cost, in the currency of campaign_budget_currency_code. Identical to spend on all 36,108 rows checked.
spenddecimalAmazon's other name for cost. Equal to it on every row in the sample; requested and carried because both are in Amazon's vocabulary, not because they differ.
cost_per_clickdecimalAverage cost per click for the row. Typed as money rather than a rate because it multiplies back into money — cost_per_click times clicks is cost. Recompute from cost and clicks when aggregating rather than averaging.
purchases_1dint64Orders attributed to a click in this placement within 1 day.
purchases_7dint64Orders attributed within 7 days. Includes everything in purchases_1d.
purchases_14dint64Orders attributed within 14 days. Includes purchases_7d.
purchases_30dint64Orders attributed within 30 days. The widest window, and the one that takes longest to stop moving.
purchases_same_sku_1dint64The subset of purchases_1d that were for the advertised SKU itself rather than another product bought after the click.
purchases_same_sku_7dint64Same-SKU subset of purchases_7d.
purchases_same_sku_14dint64Same-SKU subset of purchases_14d.
purchases_same_sku_30dint64Same-SKU subset of purchases_30d.
units_sold_clicks_1dint64Units in click-attributed orders within 1 day. Counts units where purchases_1d counts orders.
units_sold_clicks_7dint64Units in click-attributed orders within 7 days.
units_sold_clicks_14dint64Units in click-attributed orders within 14 days.
units_sold_clicks_30dint64Units in click-attributed orders within 30 days.
units_sold_same_sku_1dint64Units of the advertised SKU specifically, within 1 day.
units_sold_same_sku_7dint64Units of the advertised SKU specifically, within 7 days.
units_sold_same_sku_14dint64Units of the advertised SKU specifically, within 14 days.
units_sold_same_sku_30dint64Units of the advertised SKU specifically, within 30 days.
sales_1ddecimalAttributed sales value within 1 day, in the row's currency.
sales_7ddecimalAttributed sales value within 7 days. Includes sales_1d.
sales_14ddecimalAttributed sales value within 14 days. Includes sales_7d.
sales_30ddecimalAttributed sales value within 30 days. Includes sales_14d.
attributed_sales_same_sku_1ddecimalThe part of sales_1d that came from the advertised SKU itself. The gap between the two is other products bought after the click.
attributed_sales_same_sku_7ddecimalSame-SKU part of sales_7d.
attributed_sales_same_sku_14ddecimalSame-SKU part of sales_14d.
attributed_sales_same_sku_30ddecimalSame-SKU part of sales_30d.
kindle_edition_normalized_pages_read_14dint64KENP pages read within 14 days, for Kindle Unlimited titles. Present on every row and zero on all 36,108 in the validation sample, which had no KDP advertiser — empty, not absent.
kindle_edition_normalized_pages_royalties_14ddecimalRoyalties on those KENP pages. Zero throughout the sample for the same reason. Where it is not zero, it is revenue that no sales column includes.

Use cases

Comparing ACOS by placement. ACOS is cost ÷ sales_7d, or whichever window you have standardised on, and computed per placement_classification within a campaign it tells you whether Top of Search on-Amazon converts well enough to justify what it costs relative to Detail Page on-Amazon. The campaign report cannot answer this; it is the reason this report exists.

Setting placement bid adjustments with evidence. Amazon lets a campaign bid up for top of search and product page placements. This report is the read-back on that decision: one campaign's rows side by side, at the same attribution window, is the only fair comparison. Amazon's own help page points the same way: understand performance by placement, then adjust bids by placement in the campaign manager.

Finding where the budget goes. cost by placement_classification within a campaign-day is the spend split. A campaign that spends most of its campaign_budget_amount in Other on-Amazon and converts in Top of Search on-Amazon has a bidding problem, not a budget one.

Auditing Off Amazon spend. Filter placement_classification to Off Amazon and sum cost and sales_7d. It was the smallest slice by row count in the sample; whether it earns its spend is a per-campaign question this report answers directly.

Separating halo from direct sales by placement. sales_7d minus attributed_sales_same_sku_7d is revenue from other products bought after the click. A placement with poor same-SKU ACOS and strong total ACOS is selling the catalogue rather than the advertised SKU, and judging it on same-SKU alone would have you bid it down.

Trending Top of Search share. impressions for Top of Search on-Amazon over the campaign's total impressions, by date, is the share of your impressions that landed at the top of results. A falling share with a steady bid is the auction moving against you.

Limitations and gotchas

Attribution windows nest — never add them. sales_30d contains sales_14d contains sales_7d contains sales_1d. Summing them inflates revenue roughly fourfold.

Campaign columns repeat per placement. campaign_budget_amount and the other campaign_* columns describe the campaign, and they appear on each of its three or four placement rows for the day. Summing the budget across rows counts it several times; take it from any one row.

placement_classification is Amazon's spelling, verbatim. Nothing normalises it. Group on the exact string — spaces, hyphen and capitalisation included — and expect labels rather than enum codes. Four values have been seen in production; treat a fifth as new, not as a typo.

Reconciling to the campaign report. This is the same campaign roll-up cut by placement, so the placement rows for a campaign-day should reconstitute its campaign report row. Whether they do so exactly, to the cent, has not been checked against production files.

cost and spend are the same number. Equal on all 36,108 rows checked, as they are at the campaign grain. Read either; never add them.

Rate columns are per row. click_through_rate is a percentage — it reaches 100.0 — not a fraction, and it is null on rows with no impressions, 3.8% of the sample. Both it and cost_per_click are computed per row; averaging them across placements or days weights a 12-impression row the same as a 120,000-impression one. Recompute from clicks, impressions and cost.

Empty is not absent. The three rule-based budget columns are null on every row of the sample and both KENP columns are zero, because no advertiser in it used budget rules or advertised Kindle titles. All 44 columns arrive on every file regardless. A pipeline that infers types from values will type those columns as null and flip eight money columns between integer and double from file to file — the inferred schema differed in all 14 files, including column order — which is why the schema here is pinned rather than read off the data.

Recent days keep moving. The windows reach 30 days, so a day's purchases and sales are not final until a month after it. A re-pull of a window restates every day in it completely, and a day with no rows produces no file at all — an empty day withdraws nothing from what you already had.

campaign_id is a string. It arrives as a 12 to 15 digit number and is carried as text. Join on it as text, and never on campaign_name.

FAQ

What do the placement values mean?

Detail Page on-Amazon is ads on product detail pages, Top of Search on-Amazon is ads at the top of search results, Other on-Amazon is every other on-site position, and Off Amazon is ads served outside Amazon's own properties. Those are the four labels seen in production, and they arrive exactly as written.

Is this a different report from the campaign report?

It is the same spCampaigns report type with a second groupBy value, campaignPlacement. The columns are identical apart from placement_classification, and each campaign-day appears once per placement instead of once.

Why is click_through_rate blank on some rows?

Those rows had no impressions, so there is nothing to divide by. About 3.8 percent of rows in the sample were like that. Where it is populated it is a percentage, not a fraction.

Why are the budget rule columns always empty?

Because no campaign in the file used a rule-based budget. The columns still arrive on every row; they fill in only while a budget rule is overriding the configured amount.

Are cost and spend different?

Not in practice. They were equal on every one of the 36,108 rows checked. Both are carried because both are names Amazon uses, but treat them as one number.

Why did yesterday's numbers change when I pulled again?

Attribution. A click can earn credit for a purchase up to 30 days later, so the purchases and sales columns for a recent day keep growing. Each pull restates the whole day, so the latest pull is the one to keep.

Sources

Every researched claim on this page, and the Amazon or Walmart page it came from.

  • marketplaces — advertising.amazon.com/faq — `The reporting updates are available worldwide (NA, EU, FE) wherever you can run sponsored ads.`
  • marketplaces — advertising.amazon.com/G89VFUTQUWFFN2VU — the Sponsored Products placement report help page lists availability as sellers, vendors, authors and book vendors running Sponsored Products campaigns, with no marketplace restriction; only the Amazon Business cut is limited, to 10 locales.
  • history_window — advertising.amazon.com/campaign — the spCampaigns configuration table gives `Maximum date range 31 days` and `Data retention 95 days`.
  • history_window — advertising.amazon.com/G89VFUTQUWFFN2VU — `The placement report has 2 time units available: summary or daily. The lookback window for this report is 90 days.` Amazon's two figures disagree: 90 days is what the console export offers, 95 days is the spCampaigns retention the API request above is bounded by, and the page leads with the API figure because the page is API-first.
  • latency — advertising.amazon.com/overview — `Initial impression and click data from sponsored ads campaigns is available using the API within 12 hours`, invalid traffic is monitored for up to 30 days with a recommendation to wait 5 days, and conversion data `is subject to change for up to 60 days back from the current date`.
  • latency — advertising.amazon.com/faq — `Initial conversion data is available within 24 hours` and `Restatements of conversion data occur 1, 7, and 28 days after the conversion event.`
  • how-to-get-it — advertising.amazon.com/advertising-console — `To access your reports, click ‘Measurement & Reporting’ in the sidebar, then click through to ‘Sponsored ads reports’`, then Create report, and it names the Placement report among the types.
  • how-to-get-it — advertising.amazon.com/streamline-campaign-analysis-with-unified-reporting — unified reporting went GA on 8 June 2026 at Measurement and Reporting > Reporting, and Amazon is `sunsetting Sponsored Ads reports (Measurement and reporting > Sponsored Ads reports) ... by December 31, 2026`.
  • how-to-get-it — advertising.amazon.com/placement — `For Sponsored Products, there is not a separate placement report. You can get placement-level data using the campaignPlacement groupBy in a campaign report.`
  • use-cases — advertising.amazon.com/G89VFUTQUWFFN2VU — `Once you understand each campaign’s performance by placement, you can optimize their performance by editing existing campaigns in the campaign manager using placement bid adjustment for Top of search, Product page, Rest of Search and Amazon Business placements.`
  • click_through_rate — advertising.amazon.com/columns — the v3 columns reference gives clickThroughRate as type `Decimal` with the description `Clicks divided by impressions` and states no scale, which reads as a 0-1 fraction. Production files reach 100.0, so the page follows the evidence and reads the column as a percentage.
  • placement_classification — advertising.amazon.com/columns — placementClassification is documented as `The page location where an ad appeared` with no enumerated values, on report types spCampaigns and sbPlacement only.
  • placement_classification — advertising.amazon.com/campaign — the `Group by campaignPlacement` section adds placementClassification to the campaign columns, and its only filter is `campaignSite` (values: AmazonBusiness), so Amazon Business placements are a separate filtered request rather than extra labels in an unfiltered pull. Amazon also notes `Grouping by campaignPlacement will generate the same report as grouping by campaign and campaignPlacement.`
  • placement_classification — advertising.amazon.com/G89VFUTQUWFFN2VU — the console names three on-Amazon placement groups, `top of search (first page), rest of search, and product pages`, and says `The Sponsored Products placement report is the only source for reporting on off Amazon store metrics` — consistent with the four labels seen in production files, though Amazon enumerates no values for the API column.