File Structure

A Transformation is made up of six files — three that run on the edge and three that run in the browser. Each file is optional; only the ones you fill in are invoked.

Transformation layout
playground/
├── edge/
│   ├── tagRoot        runs on the CDN edge once per event
│   ├── tagChannel     runs on the CDN edge per provider
│   └── tagInstance    runs on the CDN edge per provider instance
└── browser/
    ├── clientTagRoot      runs in the browser once per event
    ├── clientTagChannel   runs in the browser per provider
    └── clientTagInstance  runs in the browser per provider instance

Edge plugin levels

Edge files run on the EdgeTag CDN edge (Cloudflare Workers), before any channel receives the event. They have the full server-side context — PII on params.user, host data, paid-media attribution via params.userKey, and your Secrets.

  • tagRoot — runs once per event, before any channel routing. Use for rules that apply to every channel: drop an event everywhere, enrich every payload, and emit an extra event based on attribution.

  • tagChannel — runs once per provider channel. Receives params.providerId (for example facebook, klaviyo, tiktok). Use for provider-specific rules: tweak the payload only when it's going to Facebook.

  • tagInstance — runs once per provider instance, the most granular edge level. Also receives params.providerId. Use when you have multiple pixels or accounts inside a single provider and need different behavior for each.

Browser plugin levels

Browser files run in the visitor's browser before the channel's own browser tag fires. They can skip a provider's browser execution, enrich the payload with browser-only data (like window.innerWidth or document.referrer), or shape data before it reaches the channel.

  • clientTagRoot — runs once per event in the browser, before any provider tag. Use for browser-side global rules.

  • clientTagChannel — runs once per provider channel in the browser. Receives params.providerId.

  • clientTagInstance — runs once per provider instance in the browser. Also receives params.providerId.

What each file receives

File

Side

providerId?

Params shape

tagRoot

edge

payload, user, variables, platform, userCustomData, hostData, logger, userKey, providerData

tagChannel

edge

same as tagRoot, plus providerId

tagInstance

edge

same as tagChannel

clientTagRoot

browser

payload, user, settings, variables

clientTagChannel

browser

same as clientTagRoot, plus providerId

clientTagInstance

browser

same as clientTagChannel

See Code for the full reference.

Choosing the right level

Start from what you're trying to do:

  • A rule that applies to every channeltagRoot (or clientTagRoot for browser). You usually only need one root file.

  • A rule tied to a specific providertagChannel. Check params.providerId.

  • A rule tied to a specific pixel/account inside a providertagInstance.

It's common to have only one of these files filled in. Fan out across multiple levels only when you genuinely need different rules at different granularities.

Enabled stages

Empty files are skipped entirely — they aren't registered and don't add latency. You can ship a Transformation with only tagRoot filled in, and add other levels later as your rules grow.

circle-info

Playground wraps your plugin code into a registered plugin object on save. You don't write wrappers, imports, or exports — only the function bodies.

Last updated

Was this helpful?