pixellint

Blog · DSP evaluation

A DSP sandbox CAPI sample is not the event production will send.

A solutions engineer at a DSP can see the partner sample and the vendor doc. They do not own the production dataset, and they do not own the advertiser worker. The partnership review asks whether this postback will give the bidder a conversion it can match to a click. The file attached to that review is usually the sandbox.

The sandbox body is complete on purpose. event_time is ten digits because someone hand-edited it. user_data.em is a 64-character hex because the demo hasher ran. fbc is fb.1, a millisecond timestamp, and a click id that was copied from a test landing. event_id is order-demo. Action_source is website and event_source_url is a real-looking https URL. Pixellint, on the playground or as pixellint validate json, will call that body clean if it matches the Meta pack. Clean means the sample is a legal event. It does not mean production emits it.

Ask for a second artifact before you write the match into the integration brief: one redacted body from the production worker, or from the queue that will feed it, with the test field absent. Paste both. The delta is the evaluation. A solutions engineer at a DSP who signs the sandbox has signed a payload the bidder will not see.

The fields the sample fills and the webhook drops

Production webhooks are built from the order row. The order row has an id, a total, a currency, and an email. It does not have fbp or fbc unless the landing request stored them and the checkout passed them through. A server event with a hashed email and no click cookie is a legal Purchase and a weak match. The sample hid that by pasting a cookie from a browser session the webhook will never join.

The clock is the other drop. Application code uses milliseconds. The sample uses seconds because the person who built the sample read the vendor doc. If the worker posts the application clock, Meta rejects the batch when any event_time is outside the window, and a 13-digit value is far outside it. The sandbox review will not show that rejection. The first production hour will.

event_id in the sample is a string the SE can see. Production may mint a new UUID per attempt, including on retry. Meta keeps the first event_id and event_name on that Pixel ID for 48 hours and discards the later copy. A retry with a new id is a second Purchase. The sample cannot prove idempotency. Ask what the worker does on a timeout. If the answer is a new id, the match rate you forecast from the sample is a different product.

The click the DSP stored is not automatically fbc

The DSP has a click id from the auction or the click tracker. Meta wants fbc shaped as fb.1.creationMillis.fbclid, or the cookie the pixel wrote. Putting the DSP click id into user_data.fbc does not build that cookie. Putting fbclid raw into fbc fails the shape. The partner has to have captured fbclid on their landing URL and formatted it, or forwarded the cookie. A solutions engineer cannot invent that capture inside the DSP.

If the integration is the DSP posting to Meta on the advertiser's behalf, the DSP still needs the advertiser's pixel id, a token, and the click id the advertiser's site actually received. A sample that uses a pixel id from the partner's test Business Manager is a different dataset from the advertiser pixel the bidder thinks it is training. Events on the test pixel do not dedup against the live pixel. They do not train the live ad set.

Evaluate the sample with the pack, then evaluate a redacted production row with the same pack. Note which findings are errors. Note which fields are simply absent: fbc, fbp, client_ip_address, client_user_agent. Absence of a click id is not always an error in the schema. It is still the reason the bidder will not match. Write that in the brief. Do not collapse it into a single pass.

Sample versus the row the worker will post

The sample can validate. The webhook is the body that hits the dataset. Check both.

sample:  event_time 1759010400, fbc fb.1.1759010400123.AbCdEf, em <hash>, event_id order-demo
webhook: event_time 1759010400123, fbc absent, em <hash or raw>, event_id <new uuid each try>

A raw email on the webhook is an error the sample avoided. A hashed IP is an error in the other direction: client_ip_address stays plaintext, and a 64-character digest there matches nobody. The SE can catch both on the production row without a production token, by pasting the redacted JSON. They should not paste a live token into the playground or into the ticket.

The playground and the CLI are the same engine. The CLI is what the partner should run in their worker repo. The playground is what a solutions engineer can run on a file they were emailed. Installing pixellint on the DSP side does not fix the partner worker. It stops the DSP from describing a sample as a production contract.

The page URL is part of the event, and the test pixel is a different dataset

action_source website requires event_source_url, and that URL is the browser page, not the host of the API that accepted the POST. A sample that puts https://graph.facebook.com in event_source_url, or omits the field, is a different finding from a missing fbc. A solutions engineer at a DSP should reject that sample even when the rest of the demo looks filled in. Production rows copied from a queue sometimes carry the webhook URL instead, because the only URL the worker had was its own.

The pixel id is in the Graph path, not inside the data object the sample usually shows. Ask for the path, redacted of the token. A sample posted to a pixel in the partner's test Business Manager does not deduplicate against the advertiser pixel, and it does not train the live ad set. Events Manager on the advertiser account will stay flat while the partner's test account shows rows. That split is invisible if the review file is only the JSON body.

When both the pixel and the server run, the first arrival for that event_name and event_id keeps the value for about 48 hours. A sandbox that sends a demo total of 1.00, and a production retry that sends the real total under a new id, leaves both. A sandbox that sends the real total first, under the id the pixel also used, is the path that matches. The brief should name which id the pixel will send. If the partner cannot name it, the sample has not specified the join.

What to redact before the file is pasted

Keep event_name, the digit length of event_time, the presence of event_id, action_source, the shape of event_source_url, whether em is 64 hex characters, and whether fbc starts with fb.1. Drop the access token, the raw email, the raw phone, and the client IP. The playground may store what you submit. A solutions engineer at a DSP who pastes a live token into a ticket has created a credential problem beside the measurement one.

Compare the two bodies field by field in the brief: clock digits, click id present or absent, hash or raw address, stable id or a fresh UUID, pixel id in the path. A single pass line hides the absent fbc. The bidder will match on what the webhook contains. The sample is the document that proved the partner can build a legal event once. It is not the document that proved the worker does it on every order.

Pixellint on the playground is enough for a file that arrived by email. pixellint validate json is what you ask the partner to run in the worker repository, on a fixture generated from the serializer, with exit 1 failing the pull request. Installing the binary at the DSP does not change the partner's deploy. It changes what you are willing to call a contract.

What a solutions engineer at a DSP can decide before signature

The promise is a match, and the sample is not the match

Business development can sell the measurement the partner described. A solutions engineer at a DSP is the person who can see that the described payload and the emitted payload are different objects. The bidder trains on what arrives. A clean sample is a demo.

Pixellint is not affiliated with Meta or with the DSP. A pass means the artifact matches the published Meta pack. It does not mean the advertiser consented to send the identifier, and it does not mean the DSP stored the click the fbc names. Those are the next questions. They are askable only after the two bodies have been compared.

Sources

Contract pages

The dated argument is above. These pages are the field lists.

Read pixel plus CAPI Docs