Google Tag Manager
The Pixelary tag template sends your conversions to Meta, TikTok and ChatGPT Ads through Tag Manager. It loads one script, passes GTM’s consent state to Pixelary, and lets you reuse the triggers you already have.
1 Add the template to your container
In Tag Manager open Templates → Tag Templates → Search Gallery, search for Pixelary and click
Add to workspace. Or download template.tpl from the template’s repository and import it under
Templates → Tag Templates → New → ⋮ → Import.
2 Create the base tag
New tag → Pixelary Conversion Tracking. Choose Load Pixelary (base tag), paste your site key and fire it on Initialization – All Pages. Initialization runs after Consent Initialization, where banners set their defaults, so Pixelary loads early and sees the right consent state.
Tag type Pixelary Conversion Tracking
Action Load Pixelary (base tag)
Site key px_7hq2lm4x
Consent Pass Google Consent Mode state to Pixelary: on
Trigger Initialization - All Pages
The base tag loads https://cdn.pixelary.app/s/<site key>.js. Pixelary then tracks what you set up in
the dashboard: page views, forms and clicks.
3 Track conversions
Add one more Pixelary tag per conversion with Action set to Send event. Pick a standard event and attach your existing trigger.
| Action | What it does | Typical trigger |
|---|---|---|
| Load Pixelary | Loads the script; Pixelary sends what the dashboard sets up | Initialization – All Pages |
| Send event | Sends one event, such as Purchase or Lead | Thank-you page, form success, a dataLayer event |
| Identify user | Attaches customer details to the events that follow on the page | Login or sign-up success |
| Update consent | Passes consent from a banner that doesn’t set Google Consent Mode | Your banner’s consent event |
You don’t have to fire the base tag first. Each tag adds its command to a queue, and Pixelary runs the queue in order once it loads. If an event tag has its own site key, it also loads Pixelary; the script loads only once per page.
4 Publish and verify
Use Preview first: in Preview the template writes [Pixelary] messages to the browser
console when a field is dropped or a tag fails. Then submit the container, open your site and check the Install page in
the dashboard. It turns green when the first event arrives.
Send event fields
| Field | Description |
|---|---|
| Site key (optional) | Leave empty if the base tag runs on the page. Enter it if this tag should also load Pixelary. |
| Event name | A standard event (AddPaymentInfo, AddToCart, AddToWishlist, CompleteRegistration, Contact, InitiateCheckout, Lead, PageView, Purchase, Schedule, Search, StartTrial, SubmitApplication, Subscribe, ViewContent), Custom event, or a variable. Pixelary maps standard events to each platform’s own name. |
| Custom event name | Letters, digits, spaces, underscores and hyphens, up to 50 characters. |
| Value | A number such as 49.90. A comma decimal (49,90) is accepted. |
| Currency | Three-letter ISO 4217 code such as USD. |
| Content IDs | A comma-separated list, an array of IDs, or an array of GA4 items (each item_id is used). |
| Content type | Usually product, or product_group for products with variants. |
| Content name | Product or page name. |
| Number of items | Whole number. |
| Order ID | Your order or transaction ID. |
| Event ID | Optional. If your server also sends this event to the platform, use the same ID there so it is counted once. |
| Custom parameters | Extra parameters for platforms that accept them. |
| User data | Email, phone, first and last name, external ID, city, ZIP, country. For this event only. |
Send raw user data; don’t hash it. Pixelary normalizes and hashes every value separately for Meta,
TikTok and OpenAI, and sends it only when the visitor has granted ad_user_data.
Identify user
Uses the same user data fields and attaches them to every following event on the page. Empty fields are skipped; if all of them are empty the tag sends nothing and still succeeds, so it is safe to fire everywhere.
Consent in Tag Manager
With Pass Google Consent Mode state to Pixelary checked (the default), each Pixelary tag reads
ad_storage, ad_user_data, ad_personalization and analytics_storage,
sends them before its own command, and keeps them in sync when the visitor changes their choice. Consent sent from GTM
takes priority over Pixelary’s own detection of banners.
For the strictest setup, open each Pixelary tag’s Advanced Settings → Consent Settings, choose
Require additional consent for tag to fire and add ad_storage. GTM checks consent when the
trigger fires, so also fire the base tag on your banner’s “consent updated” event. That is safe: the script loads once.
Example: Purchase from the dataLayer
Your thank-you page pushes the order:
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: "purchase",
ecommerce: {
transaction_id: "ORD-1001",
value: 49.90,
currency: "USD",
items: [{ item_id: "sku-1", item_name: "T-shirt", price: 24.95, quantity: 2 }]
},
customer: { email: "jane@example.com", phone: "+1 555 010 0000" }
});
</script>
Create Data Layer Variables for ecommerce.transaction_id, ecommerce.value,
ecommerce.currency, ecommerce.items, customer.email and
customer.phone, and a Custom Event trigger for purchase. Then add a Send event tag:
- Event name: Purchase; Value, Currency, Content IDs from the variables;
- Order ID and Event ID: the transaction ID, the same one your backend uses if it sends Purchase too;
- User data: email and phone from the variables;
- Trigger: the
purchaseCustom Event.
Everything from GTM, including PageView
On the base tag check Disable automatic events. Pixelary then sends no page views, forms or clicks of its own on those pages. Add a Send event tag with PageView on All Pages and on a History Change trigger, and send forms and clicks with your own tags. Without this, a PageView tag next to automatic events would count every page twice.
Troubleshooting
| Symptom | Likely cause and fix |
|---|---|
| Tag fails with “Site key … is not valid” | The key must be px_ plus 5 to 12 lowercase letters or digits. Check the variable that holds it. |
| Tag fails with “Could not load https://cdn.pixelary.app/s/…” | An ad blocker or a Content Security Policy blocked the script. Allow script-src https://cdn.pixelary.app and connect-src https://api.pixelary.app. |
| Tags succeed but nothing arrives | No tag loaded the script. Run pixelary.q in the console: if commands pile up there, add the base tag. Also check that the domain is added to the site. |
| Events appear only after the banner is accepted | Expected: Pixelary holds events until the visitor grants consent. |
| Consent never updates | Your banner doesn’t call Consent Mode update. Check the Consent tab in Tag Assistant, or use Update consent. |
| PageView counted twice | Automatic events are on and GTM sends PageView too. Check Disable automatic events on the base tag. |
| Purchase counted twice | Use the same Event ID in this tag and in your server-side event. |
What the template can access
| Permission | Scope |
|---|---|
| Injects scripts | https://cdn.pixelary.app/s/* only |
| Accesses global variables | pixelary and pixelary.q |
| Reads consent state | ad_storage, ad_user_data, ad_personalization, analytics_storage |
| Template storage | This template only, to register consent listeners once per page |
| Logs to console | Preview and debug mode only |
The template doesn’t send requests or set cookies itself. Everything goes through the Pixelary script.
Commands the template sends
The template calls the same JavaScript API you can use on your site:
pixelary("source", "gtm", { template_version: "1.0.0" });
pixelary("config", { auto_events: false });
pixelary("consent", { ad_storage: "granted", ad_user_data: "granted", ad_personalization: "denied", analytics_storage: "granted" }, { source: "gtm" });
pixelary("track", "Purchase", { value: 49.9, currency: "USD", content_ids: ["sku-1"], order_id: "ORD-1001" }, { event_id: "ORD-1001", user: { email: "jane@example.com" } });
pixelary("identify", { email: "jane@example.com", external_id: "u_123" }); Consent banner
Pixelary sends nothing a visitor has declined. In the EEA, the UK and Switzerland it waits for the visitor’s yes before any pixel loads or any event leaves the page.
Pixelary reads these on its own, with no extra setup:
- Google Consent Mode v2
- IAB TCF 2.2
- Global Privacy Control
- Cookiebot
- OneTrust
- CookieYes
- Usercentrics
- Complianz
- iubenda
- Termly
- Osano
- CookieFirst
- Didomi (via TCF)
- Framer cookie banner
Another banner can pass its answer with one line of code. Consent & banners
Something here doesn’t match what you see? Write to hello@pixelary.app.