Get Started
Setup your endpoints, view report attributes, and examples of requests
Endpoints
Four separate endpoints support requests to create campaign and line item reports and retrieve the report data and status.
Verb | Endpoint | Description |
---|---|---|
POST | /reports/campaigns | Create a Campaign Report Request |
POST | /reports/line-items | Create a Line Item Report Request |
GET | /reports/{reportId}/status | Get Status of a Specific Report |
GET | /reports/{reportId}/output | Download Output of a Specific Report |
Report Request Attributes
Data Type: string
Description: Campaign or Line Item ID of the desired report
Accepted Values a single or a group of campaignId
or lineItemId
e.g id: CampaignId
, OR ids: ["CampaignId1","CampaignId2"
], (maximum 50 ids per call)
metrics
Data Type: string
Description: Quantitative values associated to the campaign or line item. When metrics
and dimension
is used, the reportType
is ignored.
Accepted Values: Refer to the Metrics & Dimension page for a complete list of supported metrics
dimensions
Data Type: string
Description: Attributes of your campaign or line item data. When metrics
and dimension
is used, the reportType
is ignored.
Accepted Values: Refer to the Metrics & Dimension page for a complete list of supported dimensions
reportType
Data Type: string
Description: Report types are pre-packaged reports that allow the specification of the report breakdown. They provide metrics and dimensions distribution by summary, pageType, keyword, productCategory, product, attributedTransactions, servedCategory, environment. When not using reportType
use the metrics and dimensions arrays to build your report for additional fields. When metrics
and dimensions
are used, the report type is ignored.
Accepted Values summary
, pageType
, keyword
, productCategory
, product
, attributedTransactions
, servedCategory
, environment
startDate Required
Data Type: date
Description: Earliest day to report; inclusive
Accepted Values: YYYY-MM-DDThh:mm:ss.sTZD
endDate Required
Data Type: date
Description: Latest day to report; inclusive
Accepted Values: YYYY-MM-DDThh:mm:ss.sTZD
campaignType
Data Type: enum
Description: The campaign type
Accepted Values: sponsoredProducts
, onSiteDisplays
timeZone
Data Type: string
Description: Time zone for the report
Accepted Values: database tz syntax, eg. America/New_York
, Europe/Paris
, UTC
clickAttributionWindow
Data Type: string
Description: The post-click attribution window, defined as the maximum number of days considered between a click and a conversion for attribution; conversions are attributed to the date of conversion, not the date of click; defaults to campaign settings if omitted; must be specified if viewAttributionWindow
is one of the accepted values.
Accepted Values: 7D
, 14D
,30D
viewAttributionWindow
Data Type: string
Description: The post-view attribution window, defined as the maximum number of days considered between an impression and a conversion for attribution; conversions are attributed to the date of conversion, not the date of impression; defaults to campaign settings if omitted; must be less than or equal to clickAttributionWindow
; must be specified if clickAttributionWindow
is one of the accepted values.
Accepted Values: none, 1D
,7D
, 14D
, 30D
salesChannel
Data Type: string
Description:Filter on specific sales channel: offline or online
Accepted Values: offline
, online
format Optional
Data Type: string
Description: Format of the report data returned
Accepted Values: json-compact, json-newline, json (default), csv
Reporting Asynchronous Workflow: Step 1 of 3
- First, create a request for the campaign or line item report with the desired attributes
- This generates a
reportId
representing the report
Create a Report Request
Reporting endpoints provide two separate endpoints that allow downloading reports at the campaign or line item level. Each of the following requests can be repeated for each individual report type
https://api.criteo.com/{version}/retail-media/reports/campaigns
Sample Request - Campaign Report
curl -X POST "https://api.criteo.com/{version}/retail-media/reports/campaigns" \
-H "Authorization: Bearer <MY_ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"data": {
"type": "RetailMediaReportRequest",
"attributes": {
"id": "8343086999167541140",
"metrics": ["impressions"],
"dimensions": ["date"],
"reportType": "summary",
"startDate": "2020-04-06",
"endDate": "2020-06-04",
"timeZone": "America/New_York",
"campaignType": "sponsoredProducts",
"salesChannel": "offline"
}
}
}'
import requests
import json
url = "https://api.criteo.com/{version}/retail-media/reports/campaigns"
payload = json.dumps({
"data": {
"type": "RetailMediaReportRequest",
"attributes": {
"id": "1285",
"metrics": [
"impressions"
],
"dimensions": [
"date"
],
"reportType": "summary",
"startDate": "2022-06-06",
"endDate": "2022-07-04",
"timeZone": "America/New_York",
"campaignType": "sponsoredProducts",
"salesChannel": "offline"
}
}
})
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer <MY_ACCESS_TOKEN>'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n \"data\": {\n \"type\": \"RetailMediaReportRequest\",\n \"attributes\": {\n \"id\": \"8343086999167541140\",\n \"metrics\": [\n \t\t\t\t\t\t\t\t \"impressions\"\n \t\t\t\t\t\t\t\t ],\n \t\t\t\t\t\t \"dimensions\": [\n \t\t\t\t\t\t \"date\"\n \t\t\t\t\t\t\t\t ],\n \"reportType\": \"summary\",\n \"startDate\": \"2020-04-06\",\n \"endDate\": \"2020-06-04\",\n \"timeZone\": \"America/New_York\",\n \"campaignType\": \"sponsoredProducts\",\n \t\t\t\t\t\t \"salesChannel\": \"offline\"\n }\n }\n }");
Request request = new Request.Builder()
.url("https://api.criteo.com/{version}/retail-media/reports/campaigns")
.method("POST", body)
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer <MY_ACCESS_TOKEN>")
.build();
Response response = client.newCall(request).execute();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://api.criteo.com/{version}/retail-media/reports/campaigns');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
'follow_redirects' => TRUE
));
$request->setHeader(array(
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'Authorization' => 'Bearer <MY_ACCESS_TOKEN>'
));
$request->setBody('{\n \"data\": {\n \"type\": \"RetailMediaReportRequest\",\n \"attributes\": {\n \"id\": \"8343086999167541140\",\n \"metrics\": [\n \t\t\t\t\t\t\t\t \"impressions\"\n \t\t\t\t\t\t\t\t ],\n \t\t\t\t\t\t \"dimensions\": [\n \t\t\t\t\t\t \"date\"\n \t\t\t\t\t\t\t\t ],\n \"reportType\": \"summary\",\n \"startDate\": \"2020-04-06\",\n \"endDate\": \"2020-06-04\",\n \"timeZone\": \"America/New_York\",\n \"campaignType\": \"sponsoredProducts\",\n \t\t\t\t\t\t \"salesChannel\": \"offline\"\n }\n }\n }');
try {
$response = $request->send();
if ($response->getStatus() == 200) {
echo $response->getBody();
}
else {
echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
$response->getReasonPhrase();
}
}
catch(HTTP_Request2_Exception $e) {
echo 'Error: ' . $e->getMessage();
}
https://api.criteo.com/{version}/retail-media/reports/line-items
Sample Request - Line Item Report
curl -X POST "https://api.criteo.com/{version}/retail-media/reports/line-items" \
-H "Authorization: Bearer <MY_ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"data": {
"type": "RetailMediaReportRequest",
"attributes": {
"id": "8343086999167541140",
"metrics": [
"impressions"
],
"dimensions": [
"date"
],
"reportType": "summary",
"startDate": "2020-04-06",
"endDate": "2020-06-04",
"timeZone": "America/New_York",
"campaignType": "sponsoredProducts",
"salesChannel": "offline"
}
}
}'
import requests
import json
url = "https://api.criteo.com/{version}/retail-media/reports/line-items"
payload = json.dumps({
"data": {
"type": "RetailMediaReportRequest",
"attributes": {
"id": "1285",
"metrics": [
"impressions"
],
"dimensions": [
"date"
],
"reportType": "summary",
"startDate": "2022-06-06",
"endDate": "2022-07-04",
"timeZone": "America/New_York",
"campaignType": "sponsoredProducts",
"salesChannel": "offline"
}
}
})
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer <MY_ACCESS_TOKEN>'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n \"data\": {\n \"type\": \"RetailMediaReportRequest\",\n \"attributes\": {\n \"id\": \"8343086999167541140\",\n \"metrics\": [\n \t\t\t\t\t\t\t\t \"impressions\"\n \t\t\t\t\t\t\t\t ],\n \t\t\t\t\t\t \"dimensions\": [\n \t\t\t\t\t\t \"date\"\n \t\t\t\t\t\t\t\t ],\n \"reportType\": \"summary\",\n \"startDate\": \"2020-04-06\",\n \"endDate\": \"2020-06-04\",\n \"timeZone\": \"America/New_York\",\n \"campaignType\": \"sponsoredProducts\",\n \t\t\t\t\t\t \"salesChannel\": \"offline\"\n }\n }\n }");
Request request = new Request.Builder()
.url("https://api.criteo.com/{version}/retail-media/reports/line-items")
.method("POST", body)
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer <MY_ACCESS_TOKEN>")
.build();
Response response = client.newCall(request).execute();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://api.criteo.com/{version}/retail-media/reports/line-items');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
'follow_redirects' => TRUE
));
$request->setHeader(array(
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'Authorization' => 'Bearer <MY_ACCESS_TOKEN>'
));
$request->setBody('{\n \"data\": {\n \"type\": \"RetailMediaReportRequest\",\n \"attributes\": {\n \"id\": \"8343086999167541140\",\n \"metrics\": [\n \t\t\t\t\t\t\t\t \"impressions\"\n \t\t\t\t\t\t\t\t ],\n \t\t\t\t\t\t \"dimensions\": [\n \t\t\t\t\t\t \"date\"\n \t\t\t\t\t\t\t\t ],\n \"reportType\": \"summary\",\n \"startDate\": \"2020-04-06\",\n \"endDate\": \"2020-06-04\",\n \"timeZone\": \"America/New_York\",\n \"campaignType\": \"sponsoredProducts\",\n \t\t\t\t\t\t \"salesChannel\": \"offline\"\n }\n }\n }');
try {
$response = $request->send();
if ($response->getStatus() == 200) {
echo $response->getBody();
}
else {
echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
$response->getReasonPhrase();
}
}
catch(HTTP_Request2_Exception $e) {
echo 'Error: ' . $e->getMessage();
}
Sample Response - Both
{
"data": {
"type": "RetailMediaReportStatus",
"id": "2e733b8c-9983-4237-aab9-17a42f4267cb",
"attributes": {
"status": "pending",
"rowCount": null,
"fileSizeBytes": null,
"md5Checksum": null,
"createdAt": null,
"expiresAt": null,
"message": null
}
}
}
Reporting Asynchronous Workflow: Step 2 of 3
- Next, use the
reportId
to poll the report status endpoint until one is successfully computed
Get Status of a Specific Report
This endpoint retrieves the status of a specific report. Status can be pending
, success
, failure
, or expired
https://api.criteo.com/{version}/retail-media/reports/{reportId}/status
Sample Request
curl -X GET "https://api.criteo.com/{version}/retail-media/reports/2e733b8c-9983-4237-aab9-17a42f4267cb/status" \
-H "Authorization: Bearer <MY_ACCESS_TOKEN>"
import requests
url = "https://api.criteo.com/{version}/retail-media/reports/73fb7859-301f-4371-be91-3e4ad00964aa/status"
payload={}
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer <MY_ACCESS_TOKEN>'
}
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
.url("https://api.criteo.com/{version}/retail-media/reports/73fb7859-301f-4371-be91-3e4ad00964aa/status")
.method("GET", body)
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer <MY_ACCESS_TOKEN>")
.build();
Response response = client.newCall(request).execute();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://api.criteo.com/{version}/retail-media/reports/73fb7859-301f-4371-be91-3e4ad00964aa/status');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
'follow_redirects' => TRUE
));
$request->setHeader(array(
'Accept' => 'application/json',
'Authorization' => 'Bearer <MY_ACCESS_TOKEN>'
));
try {
$response = $request->send();
if ($response->getStatus() == 200) {
echo $response->getBody();
}
else {
echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
$response->getReasonPhrase();
}
}
catch(HTTP_Request2_Exception $e) {
echo 'Error: ' . $e->getMessage();
}
Sample Response
{
"data": {
"attributes": {
"status": "success",
"rowCount": 50,
"fileSizeBytes": 9711,
"md5CheckSum": "b92bf24cd899f172907f8b001b8a5edb",
"createdAt": "2023-07-19T19:40:27.000Z",
"expiresAt": "2023-07-26T19:40:30.000Z",
"message": "rows_count=50",
"id": "16d70ce4-6917-48b8-8a55-184809dd59b5"
},
"id": "16d70ce4-6917-48b8-8a55-184809dd59b5",
"type": "StatusResponse"
},
"warnings": [],
"errors": []
}
Reporting Asynchronous Workflow: Step 3 of 3
- Finally, download the report using the report output endpoint
- Report outputs are cached for at least 1 hour before expiration
- Exact expiration is indicated by the
expiresAt
field in the /status response
Download Output of a Specific Report
This endpoint returns the specific report in the requested format
https://api.criteo.com/{version}/retail-media/reports/{reportId}/output
Sample Request
curl -X GET "https://api.criteo.com/{version}/retail-media/reports/2e733b8c-9983-4237-aab9-17a42f4267cb/output" \
-H "Authorization: Bearer <MY_ACCESS_TOKEN>"
import requests
url = "https://api.criteo.com/{version}/retail-media/reports/73fb7859-301f-4371-be91-3e4ad00964aa/output"
payload={}
headers = {
'Accept': 'application/octet-stream',
'Authorization': 'Bearer <MY_ACCESS_TOKEN>'
}
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
.url("https://api.criteo.com/{version}/retail-media/reports/73fb7859-301f-4371-be91-3e4ad00964aa/output")
.method("GET", body)
.addHeader("Accept", "application/octet-stream")
.addHeader("Authorization", "Bearer <MY_ACCESS_TOKEN>")
.build();
Response response = client.newCall(request).execute();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://api.criteo.com/{version}/retail-media/reports/73fb7859-301f-4371-be91-3e4ad00964aa/output');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
'follow_redirects' => TRUE
));
$request->setHeader(array(
'Accept' => 'application/octet-stream',
'Authorization' => 'Bearer <MY_ACCESS_TOKEN>'
));
try {
$response = $request->send();
if ($response->getStatus() == 200) {
echo $response->getBody();
}
else {
echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
$response->getReasonPhrase();
}
}
catch(HTTP_Request2_Exception $e) {
echo 'Error: ' . $e->getMessage();
}
Sample Response
Campaign Summary Report
{
"columns": [
"campaignId", "campaignName", "campaignTypeName", "date", "impressions", "clicks", "attributedOrders", "attributedUnits", "attributedSales", "ctr", "spend", "cpc", "cpo", "roas", "uniqueVisitors", "frequency"
],
"data": [
[
"1285", "End of Summer Sale", "Open Auction", "2021-01-31", 0, 0, 1, 1, 76.9400, null, 0.0000, null, 0.0000, null, null, null
],
[
"1285", "End of Summer Sale", "Open Auction", "2021-01-29", 1883, 6, 8, 8, 1749.2600, 0.0032, 3.7000, 0.6167, 0.4625, 472.7730, null, null
],
[
"1285", "End of Summer Sale", "Open Auction", "2021-02-04", 0, 0, 1, 1, 99.4600, null, 0.0000, null, 0.0000, null, null, null
],
[
"1285", "End of Summer Sale", "Open Auction", "2021-01-28", 35087, 107, 25, 25, 4381.2700, 0.0030, 96.3000, 0.9000, 3.8520, 45.4961, null, null
]
],
"rows":4
}
Campaign Attribution Report
{
"columns": [
"purchasedDate", "purchasedHour", "advDate", "advHour", "daysDifference", "campaignId", "campaignName", "lineItemId", "lineItemName", "advProductId", "advProductGtin", "advProductMpn",
"advProductName", "advProductCategory", "purchasedProductId", "purchasedProductGtin", "purchasedProductMpn", "purchasedProductName", "purchasedProductCategory", "attributedUnits",
"attributedSales", "advEngagement", "advToPurchasedProductRelationship", "salesChannel", "retailerName", "pageTypeName", "keyword", "attributionWindow"
],
"data": [
[
"2022-10-21", 16, "2022-10-21", 16, 0, "1344", "End to end testing", "2602", "LJ Test", "426292", null, null, "Arm & Hammer Pure Baking Soda, 13.5 lbs",
"hardware > tools > hammers > powered hammers", "426292", null, null, "Arm & Hammer Pure Baking Soda, 13.5 lbs",
"hardware > tools > hammers > powered hammers", 1, 8.6900, "click", "same sku", "online", "Costco", "category", "", "C30V01"
]
],
"rows": 1
}
Responses
Response | Description |
---|---|
🔵 200 | Call executed with success Report Type has been ignored - Report Type has been ignored since Dimensions and Metrics has been provided. Please remove them if you want to use one of the templates. When generating a report type using the metrics and dimensions filters for multi dimension reporting, a warning message will be presented in the 200 to inform that reportType is ignored. This is because multi dimension takes priority in this scenario. |
🔴 400 | Common Validation Errors - endDate cannot be more than 100 days from startDate - Using a date range with more than 100 days apart - reportType invalid - calling an unsupported report type will throw a 400 error- timeZone must be a valid timezone - using a time zone value that is not listed in the list tz database time zones - format invalid - using an unsupported file format |
Updated 3 days ago