Send offline sales to Criteo¶
Criteo Offline Sales lets your brand send in-store (offline) transactions to Criteo for retail media attribution and targeting. Criteo uses these transactions to attribute in-store sales back to the ads it served, and to inform ad targeting. Amperity sends one transaction line item per row, identifying each shopper by a hashed email address, a customer ID, or a retailer visitor ID.
Send offline sales to Criteo to attribute in-store purchases back to the ads that Criteo served, and to inform ad targeting. Amperity sends transaction data at the line-item level: each row returned by your query is one product within a purchase, grouped by transaction and then by shopper, and sent to Criteo’s offline sales ingestion service.
Amperity hashes email addresses before sending them; raw email addresses never leave Amperity. A shopper can also be identified by a customer ID or a retailer visitor ID. At least one identifier is required on every row.
Beta
The Criteo Offline Sales connector is currently in beta. Contact your Amperity representative to learn more.
Important
Amperity cannot confirm that Criteo received or attributed your transactions. Criteo accepts any request it can read and reports acceptance the same way whether or not the configured account is correct. A successful connection test and a run that reports no failed rows both mean only that Criteo accepted the request — not that the sales were attributed. Confirm that events landed with your Criteo Account Strategist using Criteo’s own reporting after your first send.
Build a query¶
Use a query to build a combination of data — typically from the Unified Itemized Transactions and Customer 360 tables — that returns one row per transaction line item to send to Criteo. Each row must include a transaction ID, a timestamp, a product ID, a price, a quantity, and at least one shopper identifier: an email address, a customer ID, or a retailer visitor ID. You can also include a currency code and a store ID.
Review the Offline sales fields section for the columns your query must and may return, and the How shoppers and transactions are matched section for how line items are grouped into transactions and shoppers.
Note
Criteo attributes offline sales only within two days of the transaction. Amperity enforces this window and skips rows outside it — reported as failed with the reason — so late-arriving in-store data cannot be backfilled through this connector. Any delay between an in-store sale and it reaching Amperity reduces this window.
Note
Criteo deduplicates transactions on their transaction ID, so re-sending a transaction does not count it twice. Bound your query to recent transactions so each orchestration sends new sales rather than re-sending history.
Note
Criteo matches product_id against the product catalog feed your business sends them. A line item whose product is not in that feed is rejected by Criteo and reported only in its own logs, so Amperity reports the row as sent successfully. Confirm that the product identifier your query returns is the same one your catalog feed uses.
How shoppers and transactions are matched¶
Criteo’s ingestion format carries one shopper per request, with that shopper’s transactions nested beneath, and each transaction’s line items nested under that. Amperity reassembles the flat rows your query returns into that shape: line items are grouped into transactions, and transactions are grouped by shopper, so one request is sent per shopper. Throughput is therefore measured in shoppers, not rows — a send covering many purchases by a few thousand shoppers is a few thousand requests.
Each shopper is grouped by their strongest available identifier, in this order:
email — the only identifier that keys into Criteo’s identity graph. Amperity normalizes and hashes the address before sending.
customer_id — the identifier of a signed-in shopper, stable across their logged-in sessions but meaningful only within your business.
retailer_visitor_id — an identifier for an unrecognized shopper, persistent only on the same device, so the weakest of the three.
Amperity sends every identifier a shopper’s rows agree on, not only the strongest one, because Criteo matches on whichever it recognizes. Where a shopper’s rows carry two genuinely different values for the same identifier, that identifier is omitted rather than a value being chosen at random. Where line items within one transaction disagree on timestamp, currency, or store ID, one value is used rather than the transaction being rejected.
Add orchestration¶
An orchestration defines the relationship between query results and a destination, including the destination and the frequency at which an orchestration runs.
To add an orchestration
Open the Activations page, select the Orchestrations tab, and then click the Add orchestration button. This opens the Add orchestration dialog box.
From the Object type dropdown, select Query.
From the Object dropdown, select the query for which results is sent to Criteo.
From the Destination dropdown, select a destination that is configured for sending data to Criteo.
Verify all settings.
Set the workflow to Manual. You can change this to automatic later, after verifying the end-to-end workflow.
Click Save.
Run orchestration¶
Run the orchestration manually to validate that it works.
To run the orchestration
Open the Activations page, select the Orchestrations tab, and then open the menu for the Criteo orchestration. Select Run.
The Status column for the orchestration updates to say “Waiting to start”, after which the notifications pane updates to include a notification that shows the current status.
When the orchestration has run successfully, the status is updated to “Completed”.
Data validation¶
Amperity validates each row before grouping it and drops rows that cannot be sent, so that one invalid line item does not sink a shopper’s whole request. Dropped rows are reported as failed with the reason. A row is dropped when:
Every shopper identifier — email, customer_id, and retailer_visitor_id — is empty.
transaction_id is empty.
timestamp is empty or cannot be read. A timestamp may be a full date and time, a date on its own (treated as midnight UTC), or an epoch second count.
timestamp is more than two days in the past, outside Criteo’s attribution window. Criteo would accept the row and then discard it downstream without reporting it, so Amperity skips it instead.
price is not a number, or is negative. A negative price is a refund line, which the offline sales format cannot express.
quantity is not a whole number, or is zero or less. A negative quantity is a return or exchange line, which Criteo rejects as an invalid quantity and reports only in its own logs.
Offline sales fields¶
The following table describes each column Amperity sends to Criteo. A query must return columns with the same name as listed in the “Amperity name” column; Amperity maps them to the Criteo fields automatically. Column names are matched without regard to capitalization.
Amperity name |
Criteo field |
Description |
|---|---|---|
transaction_id |
id |
Required The transaction identifier. Criteo deduplicates on this value. |
timestamp |
timestamp |
Required When the transaction occurred. Accepts a full date and time, a date on its own (treated as midnight UTC), or an epoch second count. Values that cannot be read, or that are more than two days old, are dropped. |
product_id |
item.id |
Required The product identifier for this line item. This must be the same identifier used in the product catalog feed your business sends to Criteo. Amperity cannot verify this value. Criteo rejects a line item whose product is not in that feed, reports the rejection only in its own logs, and returns success to Amperity, so the row is reported as sent. If a run reports no failed rows but sales are not attributed, check this value first. |
price |
item.price |
Required The unit price for this line item. A value that is not a number, or that is negative, is dropped. |
quantity |
item.quantity |
Required The number of units purchased for this line item. A value that is not a whole number greater than zero is dropped. |
id.email |
Optional An email address. Amperity normalizes and hashes the address before sending; the raw address is never sent. At least one of email, customer_id, or retailer_visitor_id is required. |
|
customer_id |
customer_id |
Optional The identifier of a signed-in shopper. At least one of email, customer_id, or retailer_visitor_id is required. |
retailer_visitor_id |
retailer_visitor_id |
Optional An identifier for an unrecognized shopper, persistent only on the same device. At least one of email, customer_id, or retailer_visitor_id is required. |
currency |
currency |
Optional A three-letter ISO 4217 currency code for the transaction. |
store_id |
store_id |
Optional The store the sale happened in. |