Conversion script
Install the conversion script on your confirmation page to record each conversion with its order value, currency and order id.
The Conversion script records a conversion, with its order value, currency and order id, when it happens. Put it on your confirmation page only: it records a conversion every time it runs, so a copy on every page records a conversion on every page view.
If your tag manager cannot fire a tag on the confirmation page alone, do not install this script. Use Conversion pages instead: you list the pages that mean a conversion, turn on Count conversions only from these pages, and Tapper counts them from the monitoring script you already have.
Step 1: Pick your snippet
In the sidebar, open Setup, then Website. If your workspace has more than one protected entity, first pick the one for this website with the switcher under the workspace name. In the list of areas on the left, click Monitoring, then open the Install script and consent tab.
The Conversion script section is below the monitoring script and the consent snippets. Your tracking ID is already in every snippet.
The section has four tabs. Pick the one that matches how your site is set up.
| Tab | Use it for |
|---|---|
| Google Tag Manager | A Custom HTML tag in Google Tag Manager. |
| Shopify | A Shopify store. See Install the Tapper Shopify app. |
| PrestaShop | A PrestaShop store. |
| JavaScript | Tealium iQ, or a snippet you add to your confirmation page's HTML yourself. |
Step 2: Add the script
The Google Tag Manager tab builds a Custom HTML tag that fires on your purchase trigger. The order value goes in a first block. If anything about it breaks, a second block still records a plain conversion.
On the Google Tag Manager tab, type your own variable names into Order Value variable, Currency variable and Transaction ID variable. They start as {{DLV - ecommerce.value}}, {{DLV - ecommerce.currency}} and {{DLV - ecommerce.transaction_id}}. Type each variable's name exactly as it appears in the Name column of your Tag Manager Variables list, not the value in its Data Layer Variable Name field.
Currency is optional: clear it to use your ad account's currency. Transaction ID is optional and is used to avoid counting an order twice. If Order Value and Currency point at the same variable, Tapper warns you: Currency needs a 3-letter code such as USD, not an amount.
Copy the snippet from the code box under the fields.
In GTM, open Tags, click New, choose Custom HTML as the tag type and paste the snippet into the HTML field.
Select a trigger that fires on the confirmation page only, for example your purchase event or the thank-you page view. If the tag would fire on every page, use Conversion pages instead.
This tag hands the conversion to the monitoring script and does not load it, so the monitoring tag must fire on the confirmation page too.
Give the tag a name you will recognize and click Save. Then click Submit, describe the changes, and click Publish.
If your GTM container is loaded through a Shopify customer-events pixel, use the Shopify tab instead. This tag does not work from inside a Shopify pixel.
Google Tag Manager without a data layer
If your site has no data layer with the order values, turn on My site has no dataLayer ecommerce variables on the Google Tag Manager tab of the Conversion script section. The tag then references no GTM variables at all and records a plain conversion, with no order value. If your container already has a Tapper conversion tag, replace it: running both records every purchase twice.
If the order total can be read anywhere on your thank-you page, leave the switch off instead. Create a Custom JavaScript variable in GTM that returns the order total as a number, and use its name in Order Value variable. The tab shows an example to start from.
Google Tag Manager with the Tapper template
You can use the Tapper conversion template from the GTM Community Template Gallery instead of the Custom HTML tag. It is named Tapper - Conversion Script.
- Add a tag from the template, or open your existing one.
- On a new tag, set Public Key (pk) to your Tapper public key. It is the value inside
tapper.init("...")in your monitoring script. Without it the tag sends nothing. - Map the template's three value fields to your data layer, as in the table below. Leave Currency empty to record the value in your ad account's currency. A store that sells in several currencies must map Currency.
- Keep your existing purchase trigger, then submit and publish the container.
| Template field | GTM variable to map | Data layer path |
|---|---|---|
| Order Value | {{DLV - ecommerce.value}} (Data Layer Variable). | ecommerce.value |
| Currency (optional) | {{DLV - ecommerce.currency}} (Data Layer Variable). | ecommerce.currency |
| Transaction ID (optional) | {{DLV - ecommerce.transaction_id}} (Data Layer Variable). | ecommerce.transaction_id |
With GA4 ecommerce tracking, these paths are already filled on the purchase event. Use each variable's name exactly as it appears in the Name column of your Variables list.
Step 3: Send the right values
The order value turns a conversion into a valued conversion. If you call the script yourself, the call is window.tapper.push(amount, currency, orderId, fields), where currency, order id and fields are optional. Step 4 covers fields.
- Pass the amount as a real number (
49.99), never as a string ("49.99"). - Use a 3-letter currency code, for example
USD. If you leave the currency out, the value is recorded in your connected ad account's currency. - A store that sells in several currencies must always pass a currency.
- For an amount of exactly 1, always pass the currency.
// Order value only, recorded in your connected ad account's currency
window.tapper.push(49.99);
// Explicit currency (multi-currency stores must always pass one)
window.tapper.push(49.99, 'USD');
// With your order id
window.tapper.push(49.99, 'USD', 'ORD-1042');
// Always pass currency explicitly for amounts of exactly 1
window.tapper.push(1, 'USD');Step 4: Send additional fields (optional)
You can attach a few extra details about the order to each conversion: whether it was a partner purchase, whether a voucher was applied, the subscriber status, the plan. Tapper stores them with the conversion and does not use them for bidding. A field Tapper cannot accept is skipped on its own: the conversion, its value, its currency and its order id are always recorded.
The Tapper - Conversion Script template in the GTM Community Template Gallery has no Additional fields table. To send fields, use the Custom HTML tag below.
window.tapper.push(49.99, 'EUR', 'ORD-1042', {
partner_purchase: true,
voucher_applied: false,
subscriber_status: 'new',
plan: 'annual',
});What a field can hold
| Rule | What to send |
|---|---|
| Field name | Starts with a letter, then letters, numbers or underscores, up to 40 characters. Lowercase with underscores is suggested, for example partner_purchase. |
| Spelling | Names are case sensitive, so Plan and plan arrive as two different fields. Pick one spelling and keep to it. |
| How many | The script sends the first 20 fields that have a valid name and a usable value (text of 1 to 100 characters, a number up to 9007199254740991, true or false), and leaves out the rest, whether it has loaded or not. Tapper then skips any of those 20 that break a rule below and does not replace them with later ones. So never loop a whole data layer into the object: you get 20 fields in whatever order it lists them. |
| Text | 1 to 100 characters after trimming. Longer text is skipped, never shortened. |
| Numbers | Send the number itself: a number sent as text ('29.99') stays text. A number with 8 or more digits in all, decimals included, is skipped, see the Digits row: 29999.999 is skipped, and so is a computed amount like 0.30000000000000004, so round amounts to cents. Anything above 9007199254740991 is skipped too. |
| Digits | A value made only of digits, spaces and the characters ( ) . + / -, with 8 or more digits in all (decimals count), is skipped, whether it arrives as a number or as text: it cannot be told from a phone or a card number. Give an id a letter, like T801884423. Two exceptions. A date written as text in the form year-month-day, 2026-10-21, is kept; 2026/10/21 and 21.10.2026 are skipped. A Unix time, a whole number of seconds (10 digits) or milliseconds (13 digits) between 9 September 2001 and 18 May 2033, is kept when one of the words in its field name is at, time, timestamp, ts, epoch or date. Words are split by underscores and capital letters, so subscription_started_at and startedAt qualify and startedat does not. Send a date outside that window, such as a subscription that ends after 2033, as text like 2041-10-21. |
| True or false | Kept as sent. |
| Empty | A field with no value is skipped. 0 and false are values and are kept. |
| Lists and objects | Not accepted. Send one value per field. For line items, coupons and payment methods use Send orders from your servers. |
| Personal data | Also skipped: a hex string of 32 characters or more, a hash, an IP address (with or without a port), an IBAN, an email address, a phone number and a street address. |
| Field names to avoid | A field whose name points at a person is skipped whatever its value: email, phone, msisdn, whatsapp, first_name, birth_date, name_on_card, recipient_name, address, city, postal_code and the like. So is one that points at a secret: cvv, pin, otp, password, token, api_key and the like. |
In Google Tag Manager
The Google Tag Manager tab of the Conversion script section (Step 1) builds this tag for you. Under Additional fields, click Add field once for each field, up to 20, and fill in its row: Field name is the name the conversion carries, GTM variable is the variable that holds its value, typed as in the Name column of your Variables list. A row with an invalid or repeated name is marked and left out of the tag. The section is hidden while My site has no dataLayer ecommerce variables is on. The code box then holds three blocks, like the tag below.
The fields go in a block of their own above the conversion, so a mistake in them never stops it. If you write the tag yourself, replace each variable reference with the name of your own GTM variable, exactly as it appears in the Name column of your Variables list.
<script>
// Block 0: additional fields. Point each value at your own GTM variable.
window.__tapperFields = {
partner_purchase: {{DLV - partner_purchase}},
voucher_applied: {{DLV - voucher_applied}},
subscriber_status: {{DLV - subscriber_status}},
plan: {{DLV - plan}}
};
</script>
<script>
// Block 1: conversion with value, currency and transaction id.
(function () { try {
var raw = {{DLV - ecommerce.value}}, cur = {{DLV - ecommerce.currency}}, oid = {{DLV - ecommerce.transaction_id}};
var f = window.__tapperFields;
var v = raw == null || String(raw).trim() === '' ? NaN : Number(raw);
if (isFinite(v) && v > 0) {
var c = cur == null ? undefined : String(cur), o = oid == null ? undefined : String(oid);
var tp = window.tapper;
if (tp && !Array.isArray(tp) && typeof tp.push === 'function') tp.push(v, c, o, f);
else (window.tapper = window.tapper || []).push([v, c, o], f);
window.__tapperFields = undefined;
window.__tapperConvDone = true;
}
} catch (e) {} })();
</script>
<script>
// Block 2: fallback when there is no order value. Still sends the fields.
(function () { try {
if (window.__tapperConvDone) { window.__tapperConvDone = false; return; }
var f = window.__tapperFields;
window.__tapperFields = undefined;
var tp = window.tapper;
if (tp && !Array.isArray(tp) && typeof tp.push === 'function') tp.push(1, undefined, undefined, f);
else (window.tapper = window.tapper || []).push(1, f);
} catch (e) {} })();
</script>Keep the three blocks separate. A variable that does not exist in your container leaves its {{ }} text in the tag, which breaks that block alone, so a mistake in the fields costs the fields and not the conversion.
Until the monitoring script has loaded, window.tapper is a plain array that
holds what you push. Push the conversion and the fields there as two entries,
window.tapper.push([49.99, 'EUR', 'ORD-1042'], fields), rather than as one
four-item list. A four-item list is only accepted when its second item is a
valid currency code: without one, the conversion is lost. Two entries work
with or without a currency. The tag above already does this.
Send facts about the transaction, never details about the person. A one-time
voucher code points at one person, so send voucher_applied rather than the
code itself.
Step 5: Verify
Use GTM's Preview mode to confirm the tag fires on your confirmation page, and only there.