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

All reports
Amazon Ads Console
Search Terms & Keywords

Amazon Sponsored Products Keyword Report

The Sponsored Products keyword report gives you one row per manual keyword per day — broad, phrase and exact — with the keyword's bid, impressions, clicks, cost, top-of-search share and the attributed purchases, units and sales behind them at 1, 7, 14 and 30 days. It is the keyword half of Amazon's spTargeting report, the same request as the targeting report filtered to the three keyword match types, and the report where a keyword's bid and what the auction actually charged for it sit on the same row.

Known upstream as
spTargeting
One row is
One row per keyword
Refreshed
Daily
Columns
52
Marketplaces
All marketplaces
History
Amazon retains 95 days of Sponsored Products spTargeting data and caps one request at a 31-day range, so a full window takes four requests and anything older has to be accumulated by pulling daily; a re-pull of a window fully restates every day in it. The console's own targeting report offers a 90-day lookback.
Latency
Amazon publishes initial impression and click data within 12 hours, and says clicks and impressions can still change for up to three days while invalid traffic is filtered. Initial conversion data lands within 24 hours and is restated 1, 7 and 28 days after the conversion event, so with the 30-day attribution columns a recent day keeps restating for weeks. Report generation itself can take up to three hours after the request.
Requires
Amazon Ads API access

What this report contains

One row per manual keyword per day, for Sponsored Products. This is the keyword half of Amazon's spTargeting report: grouped by targeting, daily, and filtered to the keywordType values BROAD, PHRASE and EXACT. Across 14 production files and 511,413 rows the split was 219,531 exact, 148,495 phrase and 143,387 broad, and every file carried the same 52 columns.

The columns fall into four groups. Where the keyword lives — campaign_, ad_group_ and portfolio_id, with the campaign's budget and its currency copied onto every row. The keyword itself — keyword_id, keyword, targeting, keyword_type, match_type and keyword_bid. Delivery — impressions, clicks, click_through_rate, top_of_search_impression_share, cost and cost_per_click. Outcomes, repeated at 1, 7, 14 and 30 days for purchases, units and sales, then again for the same-SKU subset of each, and at 7 days only for the other-SKU remainder. acos_clicks_ and roas_clicks_ at 7 and 14 days are Amazon's own ratios of money columns already in the row.

Two column pairs are the same thing twice, and knowing that saves a morning. keyword and targeting are equal on every one of the 511,413 rows, and so are keyword_type and match_type. targeting and keyword_type are the general spTargeting spellings that cover automatic targets too; this report filters to the keyword types, where they collapse onto the keyword's own text and match type. All four are carried because all four are in Amazon's vocabulary and a consumer reading either name should find it.

How to get it

In the Amazon Ads console, this is Measurement & Reporting → Sponsored ads reports → Create report, with Sponsored Products as the ad product and Targeting as the report type, on the daily rather than the summary time unit. There is no keyword-only report for Sponsored Products in the console — the console's Keyword report is the Sponsored Brands one — so separating keywords from automatic targets is something you do in the API request.

Through the Amazon Ads API v3, you POST to /reporting/reports with reportTypeId: spTargeting, adProduct: SPONSORED_PRODUCTS, groupBy: ["targeting"], timeUnit: DAILY and format: GZIP_JSON, listing the 52 columns above, with a keywordType filter of ["BROAD", "PHRASE", "EXACT"]. Amazon returns a report ID; poll it until COMPLETED and download the gzipped JSON array it hands back. Generation can take as long as three hours. That request is Amazon's own “Sponsored Products: Keywords only” sample, filter and all.

The filter is the report. The targeting report is this exact request with keywordType set to the automatic target types instead. Leave the filter off and both halves land in one file with the same 52 columns and nothing but the values in keyword_type to tell them apart. Keep the two pulls separate and separately named.

Three properties of the v3 response to rely on. You get exactly the columns you asked for: all 52 arrived in every one of 14 files, in one identical set, so a missing column is your request, not Amazon's schema, and the sparse columns are present-and-null rather than absent. The order of keys in the JSON is whatever Amazon produced that day — it differed in all 14 files — so read by name, never by position. And keyword_id, campaign_id, ad_group_id and portfolio_id arrive as JSON numbers of 12 to 15 digits; cast them to strings on the way in, because they are join keys and a numeric type loses a leading zero silently.

Reports are per-profile, so a seller in five marketplaces runs five requests and gets five files, each in its own currency — campaign_budget_currency_code tells you which.

Sample rows

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

datekeywordmatch_typekeyword_bidimpressionsclickscostcost_per_clickpurchases_7dsales_7d
2026-09-14stainless steel water bottleEXACT1.2018450312296.400.95411229.59
2026-09-14insulated water bottlePHRASE0.909620154107.800.7012359.88
2026-09-14water bottleBROAD0.6542310388213.400.5519569.81
2026-09-14gym bottle 32 ozEXACT1.0521402723.760.88259.98
2026-09-14kids water bottleBROAD0.50118093.780.4200.00

Field reference

ColumnTypeDescription
datedateThe advertising day the row's metrics are attributed to, as ISO YYYY-MM-DD on every measured row. A day, not an instant — there is no time or offset to normalise, and it is the column to partition on.
campaign_idstringAmazon's campaign identifier. It arrives in the JSON as a 12 to 15 digit 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. A label for reading, not a key — join on campaign_id.
campaign_statusstringThe campaign's status. Configuration rather than a metric, copied onto every keyword row in the campaign.
campaign_budget_amountdecimalThe campaign's configured budget, repeated on every keyword row in the campaign. Summing it across keywords multiplies the budget by the number of keywords.
campaign_budget_typestringThe kind of budget campaign_budget_amount is. Configuration, repeated per keyword row.
campaign_budget_currency_codestringThe currency of campaign_budget_amount, populated on every row. In every measured file it agrees with the profile's marketplace (ten currencies from AED to USD across the sample), so today it is also the currency of every money column in the row — but it is named for the budget because that is what it strictly means.
ad_group_idstringAmazon's ad group identifier, a 12 to 15 digit number carried as a string for the same reason as campaign_id.
ad_group_namestringThe ad group's name. Join on ad_group_id, not on this.
portfolio_idstringThe portfolio the campaign sits in, if any. Null on about three quarters of rows, because most campaigns are in no portfolio; present-and-null, not missing.
keyword_idstringAmazon's identifier for the keyword, the row's key together with date. A 12 to 15 digit number carried as a string.
keywordstringThe keyword text you bid on. Equal to targeting on every one of 511,413 measured rows.
targetingstringThe targeting expression in Amazon's general spTargeting vocabulary. Because this report is filtered to keyword types, it collapses onto the keyword itself and equals keyword on every row. Both are carried so a consumer reading either name finds it.
keyword_typestringBROAD, PHRASE or EXACT. Equal to match_type on every measured row; in the sample the split was 219,531 EXACT, 148,495 PHRASE and 143,387 BROAD.
match_typestringThe keyword's match type — the same value as keyword_type on every row. Carried under both names because both are in Amazon's vocabulary.
keyword_biddecimalThe bid set on the keyword — money, because a bid is what a click may cost. Null on about 7% of rows, where the campaign's bidding strategy sets no per-keyword bid; a null is not a zero bid.
impressionsint64Times an ad matched through this keyword was displayed on the day.
clicksint64Clicks on those ads. The billable event for Sponsored Products.
click_through_ratefloat64Clicks divided by impressions as a percentage bounded at 100, not a 0 to 1 fraction. Null on about a fifth of rows, where there were no impressions. Recompute from the counts over any aggregate rather than averaging this column.
top_of_search_impression_sharefloat64Amazon's top-of-search impression share for the keyword-day, as a percentage bounded at 100. Null on about a quarter of rows.
costdecimalWhat the day's clicks cost. The only spend column in this report — unlike the campaign report there is no spend twin to reconcile.
cost_per_clickdecimalAverage cost per click for the row, typed as money because it multiplies back into money (cost_per_click times clicks is cost). Recompute from cost and clicks when aggregating.
purchases_1dint64Orders attributed to a click on this keyword 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 slowest to settle.
purchases_same_sku_1dint64The subset of purchases_1d that were 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.
units_sold_other_sku_7dint64Units of products other than the advertised SKU, within 7 days. The only window at which spTargeting carries the other-SKU split.
sales_1ddecimalAttributed sales value within 1 day.
sales_7ddecimalAttributed sales value within 7 days — the denominator behind acos_clicks_7d, and the number to divide cost by yourself when you need an exact ACOS.
sales_14ddecimalAttributed sales value within 14 days.
sales_30ddecimalAttributed sales value within 30 days.
attributed_sales_same_sku_1ddecimalThe portion of sales_1d from the advertised SKU itself.
attributed_sales_same_sku_7ddecimalSame-SKU portion of sales_7d. Amazon's definitions are complementary — this column is the purchased SKU matching the advertised one, sales_other_sku_7d is the purchased SKU differing — but Amazon states no arithmetic between the two and sales_7d, and it is not measured in the files behind this page. Read sales_7d minus this column as an estimate of halo, not as a figure guaranteed to equal sales_other_sku_7d.
attributed_sales_same_sku_14ddecimalSame-SKU portion of sales_14d.
attributed_sales_same_sku_30ddecimalSame-SKU portion of sales_30d.
sales_other_sku_7ddecimalAttributed sales of products other than the advertised SKU, within 7 days. Carried at 7 days only because that is the only other-SKU window Amazon offers for spTargeting — the 1-, 14- and 30-day counterparts exist in the columns reference but for other report types.
acos_clicks_7dfloat64Amazon's own cost divided by sales_7d, as a percentage (up to 548.8 in the measured files), not a 0 to 1 fraction. Null on about 98% of rows, wherever there were no attributed sales — a null is not a zero ACOS. For exactness divide cost by sales_7d yourself.
acos_clicks_14dfloat64The 14-day ACOS percentage, with the same nulls and the same advice as acos_clicks_7d.
roas_clicks_7dfloat64Amazon's own sales_7d divided by cost, as a bare multiple (up to 10,886 in the measured files). Null on about 93% of rows, wherever there were no clicks to spend on.
roas_clicks_14dfloat64The 14-day ROAS multiple, with the same nulls as roas_clicks_7d.

Use cases

Comparing your bid with what the auction charged. keyword_bid is what you set and cost_per_click is what a click actually cost, on the same row. A keyword whose CPC sits well under its bid has headroom you are not using; one whose CPC equals its bid is being capped by you, not by competition. Where keyword_bid is null the campaign's bidding strategy is setting the bid, and there is nothing at the keyword level to compare.

Deciding which match types earn their spend. Group by match_type, sum cost and sales_7d, and compute ACOS yourself over the aggregate. Broad, phrase and exact behave differently for most catalogues, and this is the report that separates them by day and by keyword rather than rolling them into the campaign.

Buying top of search deliberately. top_of_search_impression_share sits on the same row as cost and purchases_7d, so you can see whether the keywords winning the top slot are the ones that convert or just the ones that cost most.

Separating halo from direct sales. sales_other_sku_7d and units_sold_other_sku_7d are products people bought other than the advertised one. A keyword with weak same-SKU ACOS and strong total ACOS is introducing shoppers to the range; judged on attributed_sales_same_sku_7d alone it looks like waste.

Building a keyword history that survives re-pulls. date is a plain day with no offset, so partition on it. A re-pulled window restates every one of its days completely, which means you can supersede a day by its latest run instead of deduplicating overlapping windows — and you should, because the attribution columns keep moving for 30 days.

Multi-marketplace roll-ups. campaign_budget_currency_code is populated on every row and agrees with the profile's marketplace, so it is the column to convert on when ten currencies land in the same table.

Limitations and gotchas

Attribution windows nest — never add them. purchases_30d contains purchases_14d contains purchases_7d contains purchases_1d, and the same holds for units and sales. Summing the four inflates the number roughly fourfold.

The ACOS and ROAS columns are mostly null, and that is correct. acos_clicks_7d and acos_clicks_14d are null on 98.3% of rows (no attributed sales) and roas_clicks_7d and roas_clicks_14d on 92.8% (no clicks). A null is not a zero: a keyword with spend and no sales has an undefined ACOS, not 0%. Recompute both from cost and sales_7d over any aggregate, which also gets you full precision instead of a rounded ratio.

ACOS is a percentage; ROAS is a multiple. In the measured files ACOS ran as high as 548.8 and ROAS as high as 10,886. click_through_rate and top_of_search_impression_share are percentages bounded at 100. None of the four is a 0 to 1 fraction, and a pipeline that divides by 100 on one and not another will be quietly wrong.

A null bid is not a zero bid. keyword_bid is null on 7.3% of rows, where a campaign bidding strategy sets no per-keyword bid. Treating it as 0 makes those keywords look free.

keyword equals targeting here — do not assume it everywhere. The equality is a consequence of filtering to the keyword types, where the general spTargeting spellings collapse onto the keyword's own. Outside those types the two need not agree, so a pipeline built on this report should not carry that assumption into the targeting report.

Other-SKU exists only at 7 days. Amazon's columns reference carries salesOtherSku and unitsSoldOtherSku at 1, 14 and 30 days too, but not for spTargeting — this report type gets the 7-day pair and nothing else. A halo analysis at 14 or 30 days therefore has to subtract attributed_sales_same_sku_Nd from sales_Nd, which assumes the same-SKU and other-SKU figures partition the total. Amazon's definitions of the three are complementary but it publishes no such identity, and none is measured in the files behind this page, so treat that subtraction as an estimate.

Budget columns repeat per keyword. campaign_budget_amount is the campaign's budget copied onto every keyword row in that campaign. Summing it across an ad group multiplies the budget by the number of keywords.

There is no spend column. cost is the only spend figure — a difference from the campaign report, where both names are carried and equal.

Column order is not stable. The JSON key order differed in every one of 14 files, and a schema inferred from values flips money columns between integer and float according to whether that seller happened to have a fractional value that window. Pin the schema and read by name.

An empty day withdraws nothing. A re-pull fully restates every day that has rows, but a day on which the advertiser had no keyword rows produces no file at all. If you rely on re-pulls to clear out a bad day, check that the day actually came back.

Recent days keep changing. Amazon publishes initial click and impression data within 12 hours and can still adjust it for three days while invalid traffic is filtered; conversions arrive within 24 hours and are restated 1, 7 and 28 days after the conversion event. With a 30-day attribution column on the row, the last month restates on every re-pull.

FAQ

Is this the same report as the targeting report?

Same request, different filter. Both are spTargeting grouped by targeting with the same 52 columns; the keyword report is filtered to broad, phrase and exact keyword types and the targeting report to the automatic target types. Leave the filter off and you get both in one file.

Why are the keyword and targeting columns identical?

Because this report only contains keyword types. targeting is the general spTargeting spelling that also covers automatic targets; for a broad, phrase or exact keyword it is simply the keyword text. They were equal on every one of 511,413 measured rows, and the same is true of keyword_type and match_type.

Why is acos_clicks_7d empty on almost every row?

Because most keyword-days have no attributed sales and Amazon leaves the ratio null rather than dividing by zero. A null is not a zero ACOS. Compute ACOS over an aggregate from cost and sales_7d instead of averaging the column.

Why is keyword_bid blank on some rows?

Those keywords sit in a campaign whose bidding strategy sets no per-keyword bid, so there is no bid to report. It happened on about 7% of measured rows. Treat it as unknown at the keyword level, not as zero.

Is ACOS a percentage or a fraction in this file?

A percentage, and it can exceed 100. The measured files ran as high as 548.8. ROAS, by contrast, is a bare multiple, and click_through_rate and top_of_search_impression_share are percentages bounded at 100.

Does this report tell me what shoppers actually searched for?

No. A row is the keyword you bid on, not the query a shopper typed that matched it. Shopper queries come from the Sponsored Products search term report, which is a separate pull.

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.' Re-checked 2026-09-28; this is the published statement `all` rests on.
  • marketplaces — advertising.amazon.com/features — Sponsored Products campaigns, ad groups, product ads and keyword targeting are listed as available in US, CA, MX, BR, DE, ES, FR, IT, UK, NL, SE, TR, PL, BE, UAE, EG, SA, JP, IN, AU, SG and ZA. Ireland is not named. Rejected as this page's value rather than copied into it: the sibling Sponsored Products advertised-product report was pulled from an IE credential on 2026-09-16, so enumerating from this page would have told a reader the report is unavailable in a marketplace production files exist for.
  • marketplaces — advertising.amazon.com/api-overview#api-endpoints — the Ads API's regional host table names the same 22 marketplaces across NA, EU and FE, Ireland again absent. Rejected for the same reason as the feature-availability list.
  • history_window — advertising.amazon.com/targeting — the spTargeting configuration table gives Sponsored Products a maximum date range of 31 days and data retention of 95 days.
  • history_window — advertising.amazon.com/GPDYPV4AAYCAJFKP — Amazon's console help for the Sponsored Products targeting report: 'The lookback window for this report is 90 days.' That is the console surface, not the API's 95 days.
  • latency — advertising.amazon.com/faq — 'Initial impression and click data is available using the API within 12 hours', changes 'may happen up to three days after the initial click date due to the traffic validation process', 'Initial conversion data is available within 24 hours', and 'Restatements of conversion data occur 1, 7, and 28 days after the conversion event.'
  • latency — advertising.amazon.com/get-started — 'Report generation can take as long as three hours.'
  • 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. From here, click on Create report to set up your new custom report.'
  • how-to-get-it — advertising.amazon.com/GBYSPTSLR337JMLH — the downloadable-reports table lists Targeting as a Sponsored Products report type; the console's Keyword report is ticked for Sponsored Brands only.
  • how-to-get-it — advertising.amazon.com/GPDYPV4AAYCAJFKP — 'The targeting report has 2 time units available: summary or daily.'
  • how-to-get-it — advertising.amazon.com/get-started — every report request uses POST /reporting/reports and returns a reportId with status PENDING; you poll GET /reporting/reports/{reportId} until status is COMPLETED and a url appears, then download the gzipped JSON.
  • how-to-get-it — advertising.amazon.com/targeting — Amazon's own 'Sponsored Products: Keywords only' sample is reportTypeId spTargeting, adProduct SPONSORED_PRODUCTS, groupBy ['targeting'], format GZIP_JSON with a keywordType filter of BROAD, PHRASE and EXACT; the sample above it is the same request filtered to TARGETING_EXPRESSION and TARGETING_EXPRESSION_PREDEFINED instead.
  • faq — advertising.amazon.com/search-term — shopper queries come from the separate spSearchTerm report type, grouped by searchTerm.
  • faq — advertising.amazon.com/columns — searchTerm is 'The search term used by the customer. Same as query.', while keyword is 'Text of the keyword or a representation of the targeting expression (for Sponsored Products)'.
  • fields (same-SKU / other-SKU split) — advertising.amazon.com/columns — sales7d is 'Total value of sales occurring within 7 days of an ad click', attributedSalesSameSku7d the same 'where the purchased SKU was the same as the SKU advertised' and salesOtherSku7d 'where the purchased SKU was different from the SKU advertised'; unitsSoldClicks7d, unitsSoldSameSku7d and unitsSoldOtherSku7d are worded the same way. The definitions are complementary, but Amazon defines each column independently and states no identity between the total and the two parts — so the page calls the subtraction an estimate rather than asserting sales_7d = same + other. Not measured in the files behind this page either: the 14-file validation records nothing on this.
  • fields (other-SKU at 7 days only) — advertising.amazon.com/columns — salesOtherSku7d and unitsSoldOtherSku7d list spTargeting among their report types; salesOtherSku1d/14d/30d and unitsSoldOtherSku1d/14d/30d list only spPurchasedProduct, spPromptAdExtension, sbPromptAdExtension and spVideoAdExtension. advertising.amazon.com/targeting agrees: its spTargeting column list carries the 7-day pair and no other other-SKU window. Confirms the 52-column set rather than contradicting it.
  • fields (same-SKU / other-SKU split) — advertising.amazon.com/GPDYPV4AAYCAJFKP — the console help for the targeting report defines Sales (promoted) ('where the purchased SKU was the same as the one advertised'), Sales (halo) ('where the purchased SKU was other than the one advertised') and Sales ('the sales from purchases attributed to an ad interaction') separately, and likewise for units. It too states no arithmetic between the three.