vendor/snapchat · vendor documented
Snap CAPI writes WEB where Meta writes website
Snap CAPI and Meta CAPI post the same envelope, down to the field names. A bare payload carries no host, so the packs tell each other apart by action_source. A payload whose action_source is missing or misspelled matches both, and both report it.
Hashed identifiers, unhashed IP and user agent, and event_source_url required when action_source is WEB: same shape of contract as Meta CAPI, different enum. Snap Conversion API is not a Meta CAPI body on a Snap host.
What this pack matches
Rules
Codes are stable. A finding in CI, MCP, or the playground lands on the same id.
| Field | Required | What it checks | Rule ids | Source |
|---|---|---|---|---|
access_token |
required | The events endpoint authenticates with an access token on the request. Fix: Send the Conversions API access token, and keep it out of anything client-side. | vendor.snapchat.param.access_token.missingvendor.snapchat.param.access_token.empty |
docs |
event_name |
required | Snap documents a fixed set of event types, spelled in upper case with underscores. Fix: Use one of the documented event types, such as `PAGE_VIEW` or `PURCHASE`. | vendor.snapchat.body.event_name.missingvendor.snapchat.body.event_name.emptyvendor.snapchat.body.event_name.invalid |
docs |
event_time |
required | It is the epoch timestamp of the conversion, and Snap only accepts events from the last 7 days. Fix: Send the epoch timestamp of the conversion, not of the moment you forwarded it. | vendor.snapchat.body.event_time.missingvendor.snapchat.body.event_time.emptyvendor.snapchat.body.event_time.invalid |
docs |
action_source |
required | It says where the event took place, and Snap accepts three values. Fix: Use `WEB`, `OFFLINE`, or `MOBILE_APP`. Snap spells these in upper case, unlike Meta. | vendor.snapchat.body.action_source.missingvendor.snapchat.body.action_source.emptyvendor.snapchat.body.action_source.invalid |
docs |
event_source_url |
optional | It is the URL of the page the event happened on, and Snap requires it for web events. Fix: Send the full page URL, including the scheme. | vendor.snapchat.body.event_source_url.emptyvendor.snapchat.body.event_source_url.invalid |
docs |
event_id |
optional | It is an advertiser-chosen identifier for deduplication against the Pixel. Snap documents it as recommended for unique events. An empty pair cannot collapse a web and CAPI pair. Fix: Send the same `event_id` the Pixel used as `client_dedup_id`, or drop the empty pair. | vendor.snapchat.body.event_id.empty |
docs |
user_data |
required | Snap matches the conversion on customer information, and the event needs at least one identifier. Fix: Add a `user_data` object carrying a hashed email, hashed phone, mobile ad id, or IP and user agent pair. | vendor.snapchat.body.user_data.missing |
docs |
user_data.em |
optional | Email must be normalized and SHA-256 hashed before it is sent. Fix: Trim and lowercase the address, hash it with SHA-256, and send the hex digest. | vendor.snapchat.body.user_data.em.emptyvendor.snapchat.body.user_data.em.invalid |
docs |
user_data.em[] |
optional | Every email in the list must be normalized and SHA-256 hashed. | vendor.snapchat.body.user_data.em[].emptyvendor.snapchat.body.user_data.em[].invalid |
docs |
user_data.ph |
optional | Phone must be normalized and SHA-256 hashed before it is sent. | vendor.snapchat.body.user_data.ph.emptyvendor.snapchat.body.user_data.ph.invalid |
docs |
user_data.ph[] |
optional | Every phone number in the list must be normalized and SHA-256 hashed. | vendor.snapchat.body.user_data.ph[].emptyvendor.snapchat.body.user_data.ph[].invalid |
docs |
user_data.fn |
optional | First name must be SHA-256 hashed. | vendor.snapchat.body.user_data.fn.emptyvendor.snapchat.body.user_data.fn.invalid |
docs |
user_data.ln |
optional | Last name must be SHA-256 hashed. | vendor.snapchat.body.user_data.ln.emptyvendor.snapchat.body.user_data.ln.invalid |
docs |
user_data.ge |
optional | Gender must be SHA-256 hashed. | vendor.snapchat.body.user_data.ge.emptyvendor.snapchat.body.user_data.ge.invalid |
docs |
user_data.ct |
optional | City must be SHA-256 hashed. | vendor.snapchat.body.user_data.ct.emptyvendor.snapchat.body.user_data.ct.invalid |
docs |
user_data.st |
optional | State must be SHA-256 hashed. | vendor.snapchat.body.user_data.st.emptyvendor.snapchat.body.user_data.st.invalid |
docs |
user_data.zp |
optional | Postal code must be SHA-256 hashed. | vendor.snapchat.body.user_data.zp.emptyvendor.snapchat.body.user_data.zp.invalid |
docs |
user_data.country |
optional | Country must be SHA-256 hashed. | vendor.snapchat.body.user_data.country.emptyvendor.snapchat.body.user_data.country.invalid |
docs |
user_data.client_ip_address |
optional | It is sent unhashed, and it must be the address of the browser rather than of your server. | vendor.snapchat.body.user_data.client_ip_address.empty |
docs |
user_data.client_user_agent |
optional | It is sent unhashed, and it must be the browser's user agent rather than your HTTP client's. | vendor.snapchat.body.user_data.client_user_agent.empty |
docs |
user_data.sc_click_id |
optional | It is the Snap click ID from the landing-page `ScCid` query. Snap documents it as unhashed. Fix: Copy `ScCid` from the landing URL into `user_data.sc_click_id`, or drop the empty pair. | vendor.snapchat.body.user_data.sc_click_id.empty |
docs |
user_data.sc_cookie1 |
optional | It is the first-party `_scid` cookie. Snap documents it as unhashed and recommended for match rate. Fix: Read `_scid` under your domain into `user_data.sc_cookie1`, or drop the empty pair. | vendor.snapchat.body.user_data.sc_cookie1.empty |
docs |
user_data.madid |
optional | It is the mobile advertiser ID. Snap documents it as lowercase and unhashed. Fix: Send the IDFA or GAID in lowercase, unhashed, or drop the empty pair. | vendor.snapchat.body.user_data.madid.empty |
docs |
user_data.idfv |
optional | It is the plain-text IDFV. Snap documents it as unhashed and recommended for app events. Fix: Send the IDFV unhashed, or drop the empty pair. | vendor.snapchat.body.user_data.idfv.empty |
docs |
custom_data.value |
optional | It is the monetary value of the event. Snap documents a float, required for PURCHASE, with no currency symbol. Fix: Send the purchase total in `custom_data.value` as a number, such as `10`. | vendor.snapchat.body.custom_data.value.emptyvendor.snapchat.body.custom_data.value.invalid |
docs |
custom_data.currency |
optional | It is the currency of `custom_data.value`. Snap documents a subset of ISO 4217, not every three-letter code. Fix: Send a documented code such as `USD`. | vendor.snapchat.body.custom_data.currency.emptyvendor.snapchat.body.custom_data.currency.invalid |
docs |
custom_data.order_id |
optional | It is the order identifier. Snap documents it on the Dynamic Ads custom_data table. Fix: Send the order id in `custom_data.order_id`, or drop the empty pair. | vendor.snapchat.body.custom_data.order_id.empty |
docs |
custom_data.content_type |
optional | It says what `content_ids` or `contents` represent. Snap documents `product` for a single item or `product_group` for a variant group. Fix: Set `custom_data.content_type` to `product` or `product_group`. | vendor.snapchat.body.custom_data.content_type.emptyvendor.snapchat.body.custom_data.content_type.invalid |
docs |
custom_data.content_ids |
optional | It is a product or category identifier. Snap documents a single id, an array, or a comma-separated list. Fix: Send a catalog id in `custom_data.content_ids`, or drop the empty pair. | vendor.snapchat.body.custom_data.content_ids.empty |
docs |
custom_data.content_ids[] |
optional | Every id in the list is a product or category identifier. Fix: Send catalog ids in `custom_data.content_ids`, or drop empty entries. | vendor.snapchat.body.custom_data.content_ids[].empty |
docs |
custom_data.num_items |
optional | It is the total number of items. Snap documents it as a string. Fix: Send a whole number in `custom_data.num_items`, such as `2`. | vendor.snapchat.body.custom_data.num_items.emptyvendor.snapchat.body.custom_data.num_items.invalid |
docs |
custom_data.contents[].id |
optional | It is the item id on a contents row. Snap documents `id` on each contents object. Fix: Set `custom_data.contents[].id` to the catalog item ID, or drop the empty pair. | vendor.snapchat.body.custom_data.contents[].id.empty |
docs |
custom_data.contents[].quantity |
optional | It is the item count on a contents row. Snap's published example sends it as a number string. Fix: Send `custom_data.contents[].quantity` as a number, such as `1`. | vendor.snapchat.body.custom_data.contents[].quantity.emptyvendor.snapchat.body.custom_data.contents[].quantity.invalid |
docs |
custom_data.contents[].item_price |
optional | It is the unit price of one item. Snap's published example sends `item_price` as a number string. Fix: Send `custom_data.contents[].item_price` as a number, such as `5`. Put the order total in `custom_data.value`. | vendor.snapchat.body.custom_data.contents[].item_price.emptyvendor.snapchat.body.custom_data.contents[].item_price.invalid |
docs |
custom_data.content_name |
optional | It is the name of the page or product associated with the event. Snap documents it on the Dynamic Ads custom_data table. Fix: Send the page or product name in `custom_data.content_name`, or drop the empty pair. | vendor.snapchat.body.custom_data.content_name.empty |
docs |
custom_data.content_category |
optional | It is an item or category. Snap documents a single category or an array. Fix: Send a category in `custom_data.content_category`, or drop the empty pair. | vendor.snapchat.body.custom_data.content_category.empty |
docs |
custom_data.content_category[] |
optional | Every entry in the list is an item or category. Fix: Send categories in `custom_data.content_category`, or drop empty entries. | vendor.snapchat.body.custom_data.content_category[].empty |
docs |
custom_data.search_string |
optional | It is the text that was searched for. Snap documents it on the Dynamic Ads custom_data table. Fix: Send the query in `custom_data.search_string`, or drop the empty pair. | vendor.snapchat.body.custom_data.search_string.empty |
docs |
custom_data.predicted_ltv |
optional | It is the predicted lifetime value of the conversion. Snap documents a float. Fix: Send `custom_data.predicted_ltv` as a number, such as `120.5`. | vendor.snapchat.body.custom_data.predicted_ltv.emptyvendor.snapchat.body.custom_data.predicted_ltv.invalid |
docs |
custom_data.checkin_date |
optional | It is the hotel check-in date in the hotel's time zone. Snap documents YYYYMMDD, YYYY-MM-DD, YYYY-MM-DDThh:mmTZD, and YYYY-MM-DDThh:mm:ssTZD. Fix: Send a documented check-in date such as `20261015` or `2026-10-15`. | vendor.snapchat.body.custom_data.checkin_date.emptyvendor.snapchat.body.custom_data.checkin_date.invalid |
docs |
custom_data.origin_airport |
optional | It is the origin airport. Snap documents the official IATA code. Fix: Send a three-letter IATA code such as `JFK`. | vendor.snapchat.body.custom_data.origin_airport.emptyvendor.snapchat.body.custom_data.origin_airport.invalid |
docs |
custom_data.destination_airport |
optional | It is the destination airport. Snap documents the IATA code. Fix: Send a three-letter IATA code such as `CDG`. | vendor.snapchat.body.custom_data.destination_airport.emptyvendor.snapchat.body.custom_data.destination_airport.invalid |
docs |
custom_data.num_adults |
optional | It is the number of adults staying. Snap documents an integer on the Dynamic Travel Ads table. Fix: Send a whole number in `custom_data.num_adults`, such as `2`. | vendor.snapchat.body.custom_data.num_adults.emptyvendor.snapchat.body.custom_data.num_adults.invalid |
docs |
custom_data.num_children |
optional | It is the number of children staying. Snap documents an integer on the Dynamic Travel Ads table. Fix: Send a whole number in `custom_data.num_children`, such as `1`. | vendor.snapchat.body.custom_data.num_children.emptyvendor.snapchat.body.custom_data.num_children.invalid |
docs |
custom_data.num_infants |
optional | It is the number of infants staying. Snap documents an integer on the Dynamic Travel Ads table. Fix: Send a whole number in `custom_data.num_infants`, such as `0`. | vendor.snapchat.body.custom_data.num_infants.emptyvendor.snapchat.body.custom_data.num_infants.invalid |
docs |
body.web_requires_source_url |
required | The event is marked `action_source: WEB` but carries no `event_source_url`, which Snap requires for website events. Fix: Send the URL of the page the event took place on. | vendor.snapchat.body.web_requires_source_url |
docs |
body.purchase_requires_value_and_currency |
required | A `PURCHASE` event is missing its value or currency. Snap documents `value` as required for PURCHASE, and currency rides with that value. Fix: Send `custom_data.value` and `custom_data.currency` on PURCHASE events. | vendor.snapchat.body.purchase_requires_value_and_currency |
docs |
body.value_requires_currency |
required | The event carries `custom_data.value` with no `custom_data.currency`. Snap documents currency as the ISO code that goes with the value. Fix: Add `custom_data.currency` as a three-letter code alongside the value. | vendor.snapchat.body.value_requires_currency |
docs |
body.unhashed_email |
required | A field carries what looks like a raw email address. Snap requires customer information to be normalized and SHA-256 hashed. Fix: Trim the address, lowercase it, hash it with SHA-256, and send the hex digest. | vendor.snapchat.body.unhashed_email |
docs |
body.hashed_plaintext_field |
required | This field looks like a SHA-256 digest, but Snap documents it as one of the parameters that is sent unhashed. Fix: Send the raw value. Hashing it makes the event unmatchable. | vendor.snapchat.body.hashed_plaintext_field |
docs |
Validate a payload
pixellint validate json @payload.json --rulepack vendor/snapchat
Try this failing payload in the playground. Snap WEB event without event_source_url.
{"data":[{"event_name":"PURCHASE","event_time":1770000000,"action_source":"WEB","user_data":{"em":["buyer@example.com"]}}]}
cargo install pixellint
·
npm install pixellint