pixellint

CAPI · engineers · marketers

Test events are not a lower environment

A test code routes the payload into a debug UI. It does not point at a sandbox graph with fake users. Production tokens plus a test code is still your real pixel id. Treat it as production data with a filter, not as a toy.

What test_event_code actually does

On Meta CAPI, test_event_code diverts the event to the Events Manager test tool. It warns in Pixellint as vendor.meta-conversions-api.testing.test_event_code_present because it should not appear on live traffic. The access_token is still a production system-user token. The Pixel ID is still the production pixel.

There is no Meta sandbox graph you are safely writing to. Hashed PII in a test event is still hashed PII about a real person if you used a real checkout. Strip emails from fixtures. Use a staff order id you control.

Use it in QA

You can confirm the body arrived, which fields matched, and which were dropped, without waiting for attribution windows. Pixel Helper and Test Events together cover both pipes. Same event_id in both UIs is the hybrid test. One UI is a single-pipe test with extra ceremony.

Send a known Purchase: 10-digit event_time, website plus event_source_url, hashed em, plaintext IP/UA, value and currency. If Test Events shows the event and flags missing match keys, that is match quality, not ingest.

Strip it in prod

A leftover test_event_code means the event may never train the production model. Feature-flag the field. Do not comment it out in a shared client. Do not leave it in a config file that staging and prod share with one boolean you forgot to flip.

Pixellint warning on the live payload is the backstop, not the design. CI should assert production fixtures do not contain test_event_code. Staging fixtures should contain it on purpose.

GA4 debug is a different mechanism

Measurement Protocol has /debug/mp/collect and debug_mode on the event. They are not interchangeable with Meta's code. Hitting the debug URL with a production api_secret still validates the contract; it may not count the event the way prod /mp/collect does. Production MP returns 204 without telling you the event name was misspelled.

debug_mode left on in production is how DebugView fills with real users. That is the GA4 analog of a leftover test_event_code: a filter you meant for QA, attached to live traffic.

Staging pixels are the other option

A separate Pixel ID / measurement_id for staging is cleaner than a test flag on the production id. Then leftover flags matter less, and you cannot train prod by accident. Many teams still share the prod pixel because 'it is easier'. That is a data incident with extra steps.

If you must share an id, test_event_code and debug_mode keep hits out of reporting more or less. They do not keep hits out of your logs, your APM, or a HAR you upload to the agency.

Flag on, model off

The field is a filter, not a sandbox. Drop it before the token hits live traffic.

// QA: keep the code, still a real Pixel ID.
POST /v21.0/{pixel-id}/events?access_token=...
{
  "test_event_code": "TEST12345",
  "data": [{ "event_name": "Purchase", "event_time": 1770000000, "action_source": "website", ... }]
}

pixellint validate json @live.json --rulepack vendor/meta-conversions-api
# warning  vendor.meta-conversions-api.testing.test_event_code_present

// Prod: omit the field entirely. Do not send test_event_code: "".
{
  "data": [{ "event_name": "Purchase", "event_time": 1770000000, ... }]
}

// GA4: debug endpoint is not Meta's code.
POST https://www.google-analytics.com/debug/mp/collect?measurement_id=G-XXXX&api_secret=...

Check the artifact

Paste the pixel URL or JSON body into the playground. Same engine as pixellint validate. Nothing leaves the tab.