Skip to main content

Sponsored Product Ads Reporting

The SPA Reporting interface provides performance metrics and on-demand report generation for Sponsored Product Ads campaigns. It provides data maximum for the last 90 days excluding the present day.

It offers two usage modes:

  • Synchronous performance calculation request — fetch pre-aggregated KPIs directly for a campaign (provided by campaignId) or product (provided by combination of campaignId and SKU). These endpoints are meant to be fast because it only calculates aggregated KPIs for single campaign or product (but not for keyword).
  • Asynchronous report generation request — request a full CSV report, each report will receive an unique id (reportId). This applies for campaign, product and keyword report. Generating such a report could take more time than single KPI calculation request, you have to poll for its status using reportId and when the status becomes READY, you can download it via the provided URL. Each report will be kept for 24 hours, afterward it is deleted (this time limit is subject to be changed).

All endpoints are served under the base path /v1/spa-reporting.

Authentication & scopes

  • All requests must carry a valid OAuth 2.0 bearer token in the Authorization header.
  • The token must include the advertising-services scope.
  • The token's partner identity determines which data is visible — you can only access data belonging to your own partner_id. There is no need to pass the partner identity as a parameter; it is derived from the token.
  • Missing or invalid credentials return 401 Unauthorized; a token without the required scope or with a partner mismatch returns 403 Forbidden.

Common use cases

Descriptions & attribution logic

This is an overview of all computed KPIs and pre-calculated measures with descriptions, attributions and endpoint origins (request methods):

Legend:

  • X = available in both endpoints
  • n.a. = not available

Tip: See endpoint outputs for a streamlined overview.

OPC KPI DeutschOPC KPI EnglishAPI KPIDescriptionCampaign Performance (GET & POST)Product Performance (GET & POST)Keyword Performance (POST)
ImpressionenImpressionstotalViewsTotal ad impressions within the requested date range.XXX
KlicksClickstotalClicksTotal ad clicks within the requested date range.XXX
AusgabenSpendstotalCostsTotal ad spend (€) within the requested date range.XXX
CTRCTRclickThroughRateThe ratio of clicks to views (totalClicks / totalViews). Indicates how effectively an ad converts impressions into clicks.GETGETn.a.
CPCCPCcostPerClickThe average cost per click (totalCosts / totalClicks). Indicates the average price paid for each ad click.GETGETn.a.
ROASROASreturnOnAdSpendThe ratio of revenue to ad spend (totalSales (product-level-attributuion) / totalCosts). Indicates how much revenue is generated per euro spent on ads.GETGETn.a.
--totalOrderedSkus (Product-level-attribution)The total number of distinct product SKUs ordered attributed to ad interactions - e.g. Product A was advertised, Product A was clicked/viewed, and Product A was purchased.XXX
--totalOrderedSkus (Campaign-level-attribution)The total number of distinct product SKUs ordered attributed to ad interactions - e.g. Product A was advertised and clicked/viewed, Product B (part of the same campaign as Product A) was purchased.n.a.n.a.n.a.
--totalOrderedSkus (Brand-level-attribution)The total number of distinct product SKUs ordered attributed to ad interactions - e.g. Product A was advertised and clicked/viewed, but Product D (same brand as Product A) was purchased. Product D is not a product of the campaign.n.a.n.a.n.a.
UmsatzTotal SalestotalSales (Product-level-attribution)The total revenue (€) attributed to ad interactions - e.g. Product A was advertised, Product A was clicked/viewed, and Product A was purchased.XXX
--totalSales (Campaign-level-attribution)The total revenue (€) attributed to ad interactions - e.g. Product A was advertised and clicked/viewed, Product B (part of the same campaign as Product A) was purchased.n.a.n.a.n.a.
UmsatzTotal SalestotalSalesSellerThe total revenue (€) attributed to ad interactions - e.g. Product A was advertised and clicked/viewed, but Product D (same brand as Product A) was purchased. Product D is not a product of the campaign.n.a.Xn.a.

This is an overview of the descriptive attributes found in the reports:

AttributeDescriptionCampaign PerformanceProduct PerformanceKeyword Performance
CAMPAIGN_IDCampaign identifier from OPC.XXX
SKUProduct SKU.n.a.Xn.a.
KEYWORDKeyword with BID in a campaign.n.a.n.a.X
SEARCHTERMActual search term used by the customer.n.a.n.a.X
MATCH_TYPEMatching logic used to match keyword with the actual search term used by the customer with possible values: EXACT, BROAD, PHRASEn.a.n.a.X
EVENT_DATE_CETdate in Central European Time (CET/CEST), format: YYYY-MM-DDXXX

Overview of synchronous and asynchronous outputs

Synchronous response

These computed KPIs are returned by the synchronous performance calculation endpoints (GET /campaign-performance, GET /product-performance):

KPIsNotes
totalViews-
totalClicks-
totalCosts-
costPerClick-
clickThroughRate-
returnOnAdSpend-
totalOrderedSkus-
totalSales-
totalSalesSellerOnly from GET /product-performance

Asynchronous response

These computed KPIs are returned as reports by the asynchronous performance calculation endpoints (POST /campaign-performance, POST /product-performance, POST /keyword-performance):

Keyword Reports

KPIsNotes
TOTAL_VIEWS-
TOTAL_CLICKS-
TOTAL_COSTS-
TOTAL_SALESProduct-level attribution
TOTAL_ORDERED_SKUSProduct-level attribution
  • Default groupBy: KEYWORD

Campaign Reports

KPIsNotes
TOTAL_VIEWS-
TOTAL_CLICKS-
TOTAL_COSTS-
TOTAL_SALESProduct-level attribution
TOTAL_ORDERED_SKUSProduct-level attribution
  • Default groupBy: CAMPAIGN_ID

Product Reports

KPIsNotes
TOTAL_VIEWS-
TOTAL_CLICKS-
TOTAL_COSTS-
TOTAL_SALESProduct-level attribution
TOTAL_SALES_SELLER-
TOTAL_ORDERED_SKUSProduct-level attribution
  • Default groupBy: SKU

Rule of thumb: if you need a single number now, use the synchronous GET endpoints. If you need a detailed, exportable breakdown — or any keyword data — use the asynchronous POST endpoints to generate the required reports.

Examples of synchronous KPIs calculation requests

Get campaign KPIs for the last 7 days

Omit both fromDate and toDate to use the default 7-day rolling window.

GET /v1/spa-reporting/campaign-performance?campaignId=camp456

Get campaign KPIs for a specific date range

GET /v1/spa-reporting/campaign-performance?campaignId=camp456&fromDate=2026-03-01&toDate=2026-03-31

Get product KPIs, its SKU and the corresponded campaignId must be provided

GET /v1/spa-reporting/product-performance?campaignId=camp456&sku=SKU789&fromDate=2026-03-01&toDate=2026-03-31

Examples of Asynchronous report generation requests

Request a keyword performance report

Submit a report generation request for keyword. The response contains a reportId and you can use it to poll the report's status including a download URL when it is ready.

POST /v1/spa-reporting/keyword-performance
{
"name": "Keyword Performance Report",
"fromDate": "2026-03-01",
"toDate": "2026-03-31",
"configuration": {
"columns": ["KEYWORD", "TOTAL_VIEWS", "TOTAL_CLICKS", "TOTAL_COSTS"],
"format": "CSV"
}
}

To additionally having keyword performance broken down by search term:

{
"name": "Search Term Analysis",
"fromDate": "2026-03-01",
"toDate": "2026-03-31",
"configuration": {
"columns": ["SEARCHTERM", "TOTAL_VIEWS", "TOTAL_CLICKS"],
"groupBy": ["SEARCHTERM"],
"format": "CSV"
}
}

To have a report on only keyword matched by BROAD logic

{
"name": "Keyword Performance Report for BROAD matching type",
"fromDate": "2026-07-01",
"toDate": "2026-07-28",
"configuration": {
"columns": [
"KEYWORD",
"TOTAL_VIEWS",
"TOTAL_CLICKS",
"TOTAL_COSTS",
"TOTAL_SALES",
"MATCH_TYPE",
"TOTAL_ORDERED_SKUS",
"EVENT_DATE_CET"
],
"filters": [
{
"column": "MATCH_TYPE",
"operator": "=",
"value": "BROAD"
}
],
"format": "CSV"
}
}

Request a campaign performance report (async) with a filter

POST /v1/spa-reporting/campaign-performance
{
"name": "Campaign Report",
"fromDate": "2026-03-01",
"toDate": "2026-03-31",
"configuration": {
"columns": ["CAMPAIGN_ID", "TOTAL_VIEWS", "TOTAL_COSTS"],
"groupBy": ["EVENT_DATE_CET", "CAMPAIGN_ID"],
"filters": [
{ "column": "CAMPAIGN_ID", "operator": "=", "value": "camp456" }
],
"format": "CSV"
}
}

Request a product performance report (async)

POST /v1/spa-reporting/product-performance
{
"name": "Product Performance Report",
"fromDate": "2026-03-01",
"toDate": "2026-03-31",
"configuration": {
"columns": ["SKU", "TOTAL_VIEWS", "TOTAL_CLICKS", "TOTAL_COSTS"],
"format": "CSV"
}
}

Data availability and match types

Date parameters

All date parameters use the format YYYY-MM-DD.

For real-time query endpoints (GET /campaign-performance, GET /product-performance):

  • Both fromDate and toDate must be provided together, or neither.
  • Omitting both defaults to the last 7 days.
  • fromDate must not be after toDate — a 400 validation-error is returned otherwise.
  • Providing only one of the two dates also returns a 400 validation-error indicating which field is missing.

For async report generation endpoints (POST /keyword-performance, POST /campaign-performance, POST /product-performance):

  • Both fromDate and toDate are required fields in the request body.

Keyword match types

The keyword report now includes the KPI for additional matching logic of BROAD and PHRASE beside EXACT. This means that currently we offer only metrics coming from POSITIVE as keyword type.

** We will update when metrics for keyword type of NEGATIVE are available for reporting.

See Sponsored Product Ads Key Campaign Creation for more information.

End-to-end workflow

The asynchronous report mode follows three steps. The synchronous mode is a single GET call that returns the KPI metrics directly in the JSON response.

StepActionYou sendYou receive
1. SubmitRequest a report with a POST endpointPOST /{type}-performance with the report configuration202 Accepted{ reportId, status: IN_PROGRESS }
2. PollCheck the job status with the returned reportId, repeating until it resolvesGET /{type}-performance/status?reportId=…200 OK{ status } (IN_PROGRESSREADY / FAILED)
3. DownloadFetch the file once the status is READYGET /reports/download?reportId=…200 OK → CSV file stream (text/csv)

Notes:

  • After submitting, you receive a reportId and an initial status of IN_PROGRESS.
  • When polling, use a reasonable interval (e.g. a few seconds) rather than tight-looping. Only continue to step 3 once the status is READY; a FAILED status means you must submit a new request.
  • The generated file is available for 24 hours after generation.

Reports

A report is a simple CSV file that consists performance data for a chosen report type (campaign, product, keyword). You might chose further metadata information to include in the report. Generally to generate a report, you need to provide 3 types of information in its configuration

  • columns: the metadata (including performance data) that you want to include in the report. It will become the column in the CSV file.
  • groupBy (optional): you can provide a list of dimensional columns to have the performance data broken down in multiple levels. For example: to know total ads impression of a keyword at daily level (groupBy list of column would be: KEYWORD, EVENT_DATE_CET)
  • filters (optional): you can also specify some condition to filter the data you may want, for example: to know about total ads impression of a keyword from only one specific ads campaign (CAMPAIGN_ID='campaign_id'). Multiple filter entries are combined with AND logic.

Report configuration

Each report type exposes a fixed set of columns. Columns that represent KPI metrics are automatically aggregated with SUM() when used with a groupBy.

Report Filters

Async report requests accept an optional configuration.filters array to narrow the data included in the report. Each filter entry has the following shape:

{
"column": "CAMPAIGN_ID",
"operator": "=",
"value": "camp456"
}
  • Filterable columns: CAMPAIGN_ID, SKU. For keyword report, MATCH_TYPE could be used.

  • Allowed operators: =, !=, >=, <=, >, <

  • Multiple filter entries are combined with AND logic.

Report Job Status

Asynchronous report generation endpoints include reportId and status in their responses. The status transitions are:

  • IN_PROGRESS
    The report job has been submitted and is currently being generated. Poll the corresponding /status endpoint until the status changes.
  • READY
    The report file has been generated and is available for download.
  • FAILED
    The report generation encountered an error. A new report request must be submitted.

Only reports with status READY can be downloaded.

Poll report status until 'READY'

GET /v1/spa-reporting/keyword-performance/status?reportId={reportId}

The same pattern applies to campaign and product reports using their respective /status endpoints.

Download a completed report

Once the status is READY, download the CSV file using the reportId:

GET /v1/spa-reporting/reports/download?reportId={reportId}

The response is a streamed CSV file with the following headers:

  • Content-Type: text/csv; charset=utf-8
  • Content-Disposition: attachment; filename="<report-filename>.csv"
  • Cache-Control: no-store

Attempting to download a report that is not yet READY (or an unknown reportId) returns 404 Not Found. If the report once existed but its file has already expired and been deleted, the endpoint returns 410 Gone.

Glossary

You may take a look into our Sponsored Product Ads glossary to have an overview.

  • EVENT_DATE_CET — The date of the ad event (impression or click, format: YYYY-MM-DD), in Central European Time (CET/CEST). Used as a dimension column for daily breakdowns.
  • fromDate — Start of a date range filter (format: YYYY-MM-DD), in Central European Time (CET/CEST). Inclusive lower bound.
  • toDate — End of a date range filter (format: YYYY-MM-DD), in Central European Time (CET/CEST). Inclusive upper bound.
  • Article Attribution (Product-level-attribution) - Only sales that can be directly traced back to a click on the Sponsored Product Ad (SPA) or to a product view of a deal for the specific product are counted. Example: Product A was advertised, Product A was clicked/viewed, and Product A was purchased.
  • Campaign Attribution (Campaign-level-attribution) - Captures all sales of products within the campaign after a click on an SPA or a deal product view, regardless of whether the purchased product was the one originally clicked/viewed. Example: Product A was clicked/viewed, and Product B (part of the same campaign as Product A) was purchased.
  • Brand Attribution (Brand-level-attribution / TotalSalesSeller) - Captures all sales of the brand after a click on an SPA product of that brand, regardless of whether the purchased product was the one originally clicked/viewed. Example: Product A was clicked/viewed, and Product D (same brand as Product A) was purchased.