Conversion Tracking Pixel
Overview
The Creatable conversion pixel records each order on your order confirmation page, so Creatable can track sales related to customer engagement. It goes on the confirmation ("thank you") page and fires once per order.
Each order sends your account ID, the order ID and the line items (SKU, price, quantity). It can also send the coupon codes used and whether the buyer is a new customer.
There are two ways to install it:
- Script snippet: paste the Creatable script on the confirmation page. This works on any platform, and in Tealium, Ensighten or other tag managers as a custom HTML tag.
- Google Tag Manager: import the Creatable template. It reads your GA4
purchaseevent, so most stores need no code.
Before you start
Have these ready before you install:
- Your Creatable account ID, from your Creatable account manager.
- Access to edit your order confirmation page, or to your Google Tag Manager container.
- The order data available on that page: order ID, each line item's SKU, price and quantity, the coupon codes used, and whether the buyer is a new customer.
Install
Option 1: Script snippet
Paste the snippet on your order confirmation page and fill in the order's real values. It can go anywhere on the page. The order data is queued and sent once the library loads.
<script type="text/javascript">
(function () {
var tvpa = document.createElement('script');
tvpa.type = 'text/javascript';
tvpa.async = true;
tvpa.src = 'https://a.tvpage.com/tvpa.min.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(tvpa, s);
})();
var _tvpa = _tvpa || [];
_tvpa.push(['config', {
li: 'YOUR_ACCOUNT_ID' // from your account manager
}]);
_tvpa.push(['track', 'products', {
tid: 'ORDER-100045', // your order ID, unique per order
orders: [ // one entry per line item
{ sku: 'bb8100', price: '14.99', quantity: 4 },
{ sku: '8525PDA', price: '59.99', quantity: 1 }
],
coupons: ['SAVE10', 'CREATOR-JANE'], // optional: every coupon code used, as strings
new_customer: true // optional: true or false; leave out if unknown
}]);
</script>
Option 2: Google Tag Manager
The Creatable template reads the standard GA4 purchase event, so most stores add it without code.
- Download the template: creatable-conversion-tracking.tpl.
- In GTM, go to Templates → Tag Templates → New, open the ⋮ menu, choose Import, pick the file and Save.
- Go to Tags → New → Tag Configuration and choose Creatable Conversion Tracking.
- Enter your Creatable Account ID. Leave Environment on Production, the default, and leave Cookie domain blank (see "Optional: set the cookie domain").
- Leave Order data source on Auto-detect from GA4 ecommerce dataLayer, unless your store doesn't push a GA4
purchaseevent. - Under Triggering, add a Custom Event trigger with event name
purchase. - Save, test in Preview (see Test and verify), then Submit to publish.
In auto-detect mode, the tag reads these dataLayer values:
| dataLayer value | What it sends | Required |
|---|---|---|
ecommerce.transaction_id |
order ID (tid) |
yes |
ecommerce.items[]: item_id, price, quantity |
line items | yes |
ecommerce.coupon and each item's coupon |
coupon codes; comma-separated codes are split and repeats removed | no |
new_customer, at the top level of the push |
new customer, true or false |
no |
A purchase push the tag can read:
dataLayer.push({
event: 'purchase',
new_customer: true,
ecommerce: {
transaction_id: 'ORDER-100045',
coupon: 'SAVE10',
items: [{ item_id: 'bb8100', price: 14.99, quantity: 4 }]
}
});
Optional fields. Coupon codes and New customer can point to your own GTM variables. They replace what auto-detect reads:
- Coupon codes: a variable that returns an array of codes, or a comma-separated string.
- New customer: a variable that returns
trueorfalse. If your store uses GA4'scustomer_typeinstead, map it with a Lookup Table variable:new→true,returning→false.
No GA4 purchase event? Switch Order data source to Map fields manually. Then set Transaction ID and one Order line items row per item from your own variables.
Other tag managers
In Tealium, Ensighten or another tag manager, add the script snippet from Option 1 as a custom HTML or JavaScript tag. Fire it on the order confirmation page and fill the values from your data layer.
Data reference
Every order needs an account ID, an order ID and at least one line item. Coupon codes and the new-customer flag are optional.
| Field | Required | Type | Example | Rules |
|---|---|---|---|---|
li (in config) |
yes | string | '1759724' |
Your account ID. |
cookieDomain (in config) |
no | string | 'us.example.com' |
Scopes the Creatable visitor cookie to this domain instead of your site's top-level domain. Must be the page's hostname or a parent of it. Leave it out unless you run separate regions on subdomains. |
tid |
yes | string | 'ORDER-100045' |
Unique per order. An order without it is not recorded. Sending the same tid again counts once. |
orders[].sku |
yes | string | 'bb8100' |
Use the same SKU as in your Creatable product catalog, so the sale shows against the right product. |
orders[].price |
yes | number or string | '14.99' |
What the customer paid for one unit, after discounts, without tax or shipping. Use . for decimals, no currency symbol. |
orders[].quantity |
yes | whole number | 4 |
Units of this item. |
coupons |
no | array of strings | ['SAVE10'] |
Every coupon code applied to the order, as an array of strings, even for a single code. A plain string like "SAVE10" isn't sent. Leave it out if none. |
new_customer |
no | boolean | true |
true for a new customer, false for a returning one. You decide what counts as new. Leave it out if you don't know, for example on a guest checkout. |
Commission is worked out from price × quantity for each line. If your platform spreads an order-wide discount across the lines, send that per-line price.
Test and verify
After installing, check the request your next order sends (a test order works). A working install sends one rt=pc request per order and gets a 200 back.
debug: true to config. The page shows a box listing the order data, and the order isn't sent. Remove it before testing for real.Place a test order. Before you pay, open Chrome DevTools, go to the Network tab and type
tvpa in the filter. You should see the library (tvpa.min.js) and up to three __tvpa.gif requests:rt=cid: gets a visitor ID, on the first visit only;rt=hb: a page heartbeat;rt=pc: the conversion. This is the one to check.Check the
rt=pc request. Click it and look at its query string. It should look like this:
https://api.tvpage.com/v1/__tvpa.gif?li=YOUR_ACCOUNT_ID&X-login-id=YOUR_ACCOUNT_ID&nt=…&tr=&fl=…&hn=…&rf=…&url=…&sc=…&sr=…&ul=…&tv=0.4.0&dt=…&cid=…&rt=pc&tid=ORDER-100045&cpc[]=SAVE10&cpc[]=CREATOR-JANE&nc=true&map=sku%2Cprice%2Cquantity&pr[]=bb8100%2C14.99%2C4&pr[]=8525PDA%2C59.99%2C1
The library adds page details first (X-login-id through cid). The order data comes last, starting at rt=pc.
| Parameter | Check |
|---|---|
| request host | api.tvpage.com (stage.tvpage.com if you're testing on stage) |
li |
your account ID |
rt |
pc |
tid |
your order ID |
map |
sku,price,quantity |
pr[] |
one per line item, as sku,price,quantity |
cpc[] |
one per coupon code, if any |
nc |
true or false, if you send it |
Check the status code of the
rt=pc request:| Code | Meaning | What to do |
|---|---|---|
| 200 | Received and saved | Nothing. A 200 means the order arrived, not that a creator was credited. |
| 202 | Received | Same as 200. |
| 201 | Unknown request type | Check rt is pc. |
| 203 | Nothing recorded | rt is missing, or the account ID isn't a number. |
| 205 | Couldn't be saved on our side | Retry. If it keeps happening, contact support. |
Google Tag Manager users: tick Enable console logging in the tag, then open the confirmation page in Preview mode. The browser console shows
[Creatable] config and [Creatable] track, with the order data the tag found. Untick it before publishing.Confirm with us. Email support@creatable.com with your test order IDs and the environment, and we'll confirm they were recorded.
Optional: full attribution test. In the same browser, click a creator's link to your store, then place an order. It shows as a credited sale in your Creatable dashboard within about an hour.
Once it works, let your Creatable account manager know you're live.
Optional: test on stage first
Most stores install straight to production. If you'd rather test without touching live data, Creatable has a stage environment. Ask your account manager for a stage account ID; it's different from your production ID.
| Setting | Stage |
|---|---|
| Library URL | https://a.tvpage.com/stage/tvpa.min.js |
logUrl in config |
https://stage.tvpage.com/api/__tvpa.gif (required) |
Account ID (li) |
your stage account ID |
Script snippet: the same snippet with the stage library, your stage account ID and logUrl. Without logUrl, stage test orders go to production.
<script type="text/javascript">
(function () {
var tvpa = document.createElement('script');
tvpa.type = 'text/javascript';
tvpa.async = true;
tvpa.src = 'https://a.tvpage.com/stage/tvpa.min.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(tvpa, s);
})();
var _tvpa = _tvpa || [];
_tvpa.push(['config', {
li: 'YOUR_STAGE_ACCOUNT_ID',
logUrl: 'https://stage.tvpage.com/api/__tvpa.gif' // required on stage
}]);
_tvpa.push(['track', 'products', {
tid: 'ORDER-100045',
orders: [
{ sku: 'bb8100', price: '14.99', quantity: 4 },
{ sku: '8525PDA', price: '59.99', quantity: 1 }
],
coupons: ['SAVE10', 'CREATOR-JANE'],
new_customer: true
}]);
</script>
Google Tag Manager: set Environment to Stage and enter your stage account ID.
When you're done testing, switch back:
Library URL is https://a.tvpage.com/tvpa.min.js (GTM: Environment = Production).li is your production account ID.logUrl and debug are removed from config.
One real order shows an rt=pc request to api.tvpage.com that returns 200.
Optional: set the cookie domain
The pixel stores a first-party cookie so it can recognize the same visitor across pages. By default it scopes that cookie to your site's top-level domain (for example .example.com), which shares it across every subdomain.
If you run separate regions or brands on subdomains, such as us.example.com and global.example.com, and want each tracked on its own, set the cookie domain to the page's own hostname.
Script snippet: add cookieDomain to config:
_tvpa.push(['config', {
li: 'YOUR_ACCOUNT_ID',
cookieDomain: 'us.example.com'
}]);
Google Tag Manager: fill in the Cookie domain field in the Creatable Conversion Tracking tag. If one container serves several regional sites, use the built-in variable rather than a fixed value.
The value must be the page's hostname or a parent of it. Anything else, such as a sibling subdomain or a value with a port, is ignored and the default top-level domain is used.
Troubleshooting
| What you see | Likely cause | Fix |
|---|---|---|
No tvpa requests at all |
The script is blocked (Content Security Policy, ad blocker), or the tag didn't fire | Allow a.tvpage.com and the pixel host in your CSP. In GTM, check the trigger fired in Preview. |
rt=hb but no rt=pc |
The track call is missing, or runs before the order data exists |
Make sure track runs once the order ID and items are on the page. |
GTM tag fails, console says aborting — missing tid or empty orders |
The dataLayer has no ecommerce.transaction_id or no items |
Check your purchase push, or switch to Map fields manually. |
201 or 203 |
Wrong rt, or the account ID isn't a number |
Check rt=pc and li. |
205 |
A temporary problem on our side | Retry. If it persists, contact support. |
| Stage test orders show up in production | logUrl is missing from the stage config |
Add the stage logUrl to config (see "Optional: test on stage first"). |
JavaScript error mentioning trim |
A coupon code isn't a string | Send every code as a string, e.g. ['10'], not [10]. |
200 but no sale in your dashboard |
See the list below |
If the request returns 200 but no sale shows up, check in this order:
tid is present and not reused from an earlier order.Each
pr[] value is sku,price,quantity, with a number for price and a whole number for quantity.The buyer interacted with a creator's content or link within the last 30 days.
About an hour has passed. Sales are processed hourly.
You're looking at the right environment and account ID.
FAQ
Where exactly does the pixel go? On the order confirmation ("thank you") page, after the order is placed. Not on the cart or checkout pages.
What if the customer reloads the confirmation page? The same tid is only counted once, so a reload doesn't create a second order.
Should the price include tax, shipping or discounts? Send what the customer paid for one unit, after discounts, without tax or shipping.
Which currency? Your store's own currency, as a plain number with no symbol.
What counts as a new customer? You decide. Send true for a buyer you treat as new, false for a returning one, and leave it out if you don't know. If you already send new_customer to Google Ads, send the same value here.
Which coupon codes should I send? Every code applied to the order, each as a string.
How long until sales show up? Usually within an hour.
Which sales get credited to a creator? Orders placed within 30 days of the buyer interacting with a creator's content or link. If several creators qualify, the most recent one gets the credit.
Where do I see results? In the Creatable brand app: Analytics, then the Overview tab (sales and orders) or the Reports tab (including commission).
My checkout is a single-page app. Does that matter? Fire the track call once, when the confirmation view shows with the order data. Don't fire it again if the view re-renders.
Is stage data kept separate from production? Yes, as long as stage uses the stage library, the stage logUrl and your stage account ID.
Can each of my regional subdomains have its own visitor cookie? Yes. Set cookieDomain in config, or the Cookie domain field in GTM, to that subdomain.
Need help?
Email support@creatable.com with:
your account ID and the environment (stage or production);the order ID you tested;
a screenshot of the
rt=pc request in DevTools, showing its URL and status code.