Build a browser pixel

Receive reviewed, consented canonical events in an isolated pixel runtime.

A browser pixel consists of a version-pinned frame document and pixel script on the same app-controlled HTTPS origin. The storefront embeds the frame only when the merchant enabled the pixel and the visitor granted the declaration's consent purpose.

Security boundary#

The frame is cross-origin from the storefront and sandboxed with scripts and its own origin. It may use its own origin's storage when a provider SDK requires it, but the browser's same-origin policy prevents access to the storefront DOM, cookies, JavaScript objects, or storage. Tringify sends only the reviewed public context and projected events through postMessage.

Reviewed first-party adapters#

Some advertising SDKs require the merchant document's first-party context. Tringify may provide a named browser adapter for such a provider. An adapter is platform code with a fixed provider-specific serializer; an app cannot upload or execute arbitrary JavaScript in the merchant document. The installed release still controls the event set, payload projection, envelope fields, consent purpose, and app-owned configuration origin. Availability of an adapter is reviewed separately from an ordinary pixel frame.

Host the frame document#

pixel-frame.html html
<!doctype html>
<meta charset="utf-8">
<script src="/v1/pixel-frame.js"></script>

Serve the frame with a Content-Security-Policy whose frame-ancestors permits merchant storefront origins where the app is installed. Keep all executable URLs versioned or content-addressed so an approved release remains reproducible.

Install the frame runtime#

pixel-frame.js javascript
(() => {
  "use strict";
  let context = null;
  let started = false;
  const subscribers = [];
  const buffered = [];

  window.tringify = { pixel: {
    context: () => structuredClone(context || {}),
    subscribe: (callback) => {
      if (typeof callback !== "function") return () => {};
      subscribers.push(callback);
      for (const event of buffered) callback(event);
      return () => {
        const index = subscribers.indexOf(callback);
        if (index >= 0) subscribers.splice(index, 1);
      };
    }
  }};

  addEventListener("message", (message) => {
    if (message.source !== parent || !message.data) return;
    if (message.data.__tf === "pixel-init" && !started) {
      context = message.data.context || {};
      started = true;
      const script = document.createElement("script");
      script.src = "/v1/pixel.js";
      document.head.appendChild(script);
      return;
    }
    if (message.data.__tf !== "pixel" || !message.data.event) return;
    buffered.push(message.data.event);
    for (const callback of subscribers) callback(message.data.event);
  });
})();

Subscribe in the pixel script#

pixel.js javascript
const pixel = window.tringify?.pixel;
if (!pixel) throw new Error("Tringify pixel runtime is unavailable");

const context = pixel.context();
const unsubscribe = pixel.subscribe((event) => {
  // Map only the declared event and payload fields to your provider.
  provider.track(event.type, event.payload, { eventId: event.event_id });
});