Conversion tracking via JavaScript
Our Checkout Javascript API enables you to track conversions on third-party platforms like Facebook or Google Ads (for example: use Google’s Ecommerce Measurement to collect ecommerce related data).
When the checkout form is embedded on your website, the same API can also send checkout journey events (item selected, step changes, send mode) to your parent page. That lets you push those events into Google Tag Manager, GA4, or ad pixels on your own site, where your existing campaign attribution already lives.
How to track conversions
Once you’ve installed VaocherApp checkout form onto your website, (see instruction at https://vaocher.app/settings/installation/), you can add extra code to track the new orders (e.g. conversions).
When an order is placed successfully, we will fire an event called conversion that contains all the necessary data you need. You can simply register the event handler like below:
vaocherapp('conversion', function (payload) {
console.log(payload.$iframe); // the checkout iframe that fired this event
console.log(payload.transaction); // order / payment details
});
Payload
The conversion callback receives one object with these top-level keys:
| Key | Type | Description |
|---|---|---|
$iframe |
Element | The checkout iframe DOM element that fired this event. Useful if you have more than one checkout form on the same page |
transaction |
Object | Order and payment details for the successful purchase |
Transaction data
payload.transaction has these attributes:
| Key | Type | Description |
|---|---|---|
transaction_id |
String | The transaction ID |
amount |
Number | The total paid for the order in smallest unit(1) |
amount_with_decimal |
Number | The total paid as a decimal (for example 100 for $100.00) |
amount_with_currency |
String | The total paid, formatted with currency symbol |
currency |
String | The payment currency (for example AUD) |
test_mode |
Boolean | Whether or not this is a test order |
is_pending |
Boolean | Whether payment is still pending (for example offline / bank transfer) |
service_fee |
Number | Service fee in smallest unit(1) |
service_fee_with_decimal |
Number | Service fee as a decimal |
service_fee_with_currency |
String | Service fee, formatted with currency symbol |
shipping_fee |
Number | Shipping fee in smallest unit(1) |
shipping_fee_with_decimal |
Number | Shipping fee as a decimal |
shipping_fee_with_currency |
String | Shipping fee, formatted with currency symbol |
promotion_discount |
Number | Promotion discount in smallest unit(1) |
promotion_discount_with_decimal |
Number | Promotion discount as a decimal |
promotion_discount_with_currency |
String | Promotion discount, formatted with currency symbol |
gift_vouchers |
Array | List of generated gift voucher(s) |
order_download_url |
String | Direct download URL for the order / voucher PDF |
purchaser |
Object | The purchaser info, including name and email |
recipient |
Object | The recipient info, including name and email |
A single item in gift_vouchers has these attributes:
| Key | Type | Description |
|---|---|---|
id |
String | The gift voucher ID |
code |
String | The gift voucher unique reference code |
item |
String | The purchased menu item name |
balance |
Number | The remaining balance in smallest unit(1) |
balance_with_currency |
String | The remaining balance, formatted with currency symbol |
Example payload shape (simplified):
{
$iframe: document.querySelector('iframe'), // real HTMLIFrameElement
transaction: {
transaction_id: 'tran_0123456789',
amount: 10000,
amount_with_decimal: 100,
amount_with_currency: '$100.00',
currency: 'AUD',
test_mode: false,
is_pending: false,
service_fee: 0,
service_fee_with_decimal: 0,
service_fee_with_currency: '$0.00',
shipping_fee: 0,
shipping_fee_with_decimal: 0,
shipping_fee_with_currency: '$0.00',
promotion_discount: 0,
promotion_discount_with_decimal: 0,
promotion_discount_with_currency: '$0.00',
gift_vouchers: [
{
id: 'abcxzy-1234-5678-0000-123456789',
code: 'UNIQUE-CODE',
item: '$100 Gift Voucher',
balance: 10000,
balance_with_currency: '$100.00'
}
],
order_download_url: 'https://vaocher.app/...',
purchaser: {
name: 'Purchase name',
email: 'purchaser@mail.com'
},
recipient: {
name: 'Recipient name',
email: 'recipient@mail.com'
}
}
}
Note (1): Currencies in VaocherApp are always in smallest unit. That means 100 is equivalent to $1, whereas 10000 is equivalent to $100
Example
Below is a full example that reads values from payload.transaction:
<!-- Make sure to load VaocherApp latest embed script -->
<script type="text/javascript">(function(e,c,a,s){e[s]=e[s]||function(){(e[s].callbacks=e[s].callbacks||[]).push(arguments)};var t=c.createElement("script");t.async=1,t.defer=1,t.src=a,c.head.appendChild(t)})(window,document,"https://vaocher.app/resources/embed/embed.js?v=latest","vaocherapp")</script>
<script type="text/javascript">
vaocherapp('conversion', function (payload) {
var transaction = payload.transaction;
// Make sure you have loaded the Google Analytics embed code
// Then load the Google Analytics Ecommerce plugin (see https://developers.google.com/analytics/devguides/collection/analyticsjs/ecommerce)
ga('require', 'ecommerce');
ga('ecommerce:addTransaction', {
'id': transaction.transaction_id,
'revenue': transaction.amount_with_currency,
'currency': transaction.currency.toUpperCase(),
'shipping': '0',
'tax': '0',
'affiliation': 'VaocherApp',
});
for (var i = 0; i < transaction.gift_vouchers.length; i++) {
var giftVoucher = transaction.gift_vouchers[i];
ga('ecommerce:addItem', {
'id': transaction.transaction_id,
'name': giftVoucher.code + ' - ' + giftVoucher.item,
'sku': giftVoucher.code,
'category': giftVoucher.item,
'price': giftVoucher.balance_with_currency,
'quantity': '1',
'currency': transaction.currency.toUpperCase(),
});
}
ga('ecommerce:send');
});
</script>
⚠️ WARNING
If you’re using sku in tracking ecommerce:addItem, you need to make sure it’s value is unique for each item. Otherwise, Google Analytics Ecommerce only sends last item in transaction. See here
How to track checkout journey events
These events fire on your parent page while a customer moves through an embedded checkout form. They do not fire automatically into Google Tag Manager or GA4. You register a handler, then push the data wherever you need (for example dataLayer.push).
Use the same vaocherapp function and embed bootstrap snippet as for conversions.
Available events
| Event | When it fires | Useful for |
|---|---|---|
item_select |
Customer selects a menu item | Which vouchers customers start with |
next_step |
Customer moves to a checkout step | Funnel drop-off by step |
send_mode_switch |
Customer switches Send to someone else / Buy for yourself | Gift vs self-purchase intent |
Every journey callback also includes $iframe: the checkout iframe DOM element that fired the event. Use it when you have more than one checkout form on the same page (for example to tell which embed the customer used). You can ignore it for a single embed.
item_select
vaocherapp('item_select', function (payload) {
console.log(payload.event); // "item_select"
console.log(payload.item);
console.log(payload.$iframe); // the iframe element that fired this event
});
| Key | Type | Description |
|---|---|---|
$iframe |
Element | The checkout iframe DOM element that fired this event |
event |
String | Always item_select |
item |
Object | Selected item |
item.id |
String | Menu item ID |
item.name |
String | Menu item name |
Example item value:
{
"id": "mi_0123456789",
"name": "$100 Gift Voucher"
}
next_step
vaocherapp('next_step', function (payload) {
console.log(payload.event); // "next_step"
console.log(payload.step);
console.log(payload.$iframe);
});
| Key | Type | Description |
|---|---|---|
$iframe |
Element | The checkout iframe DOM element that fired this event |
event |
String | Always next_step |
step |
Object | Current step |
step.name |
String | Step key: item, details, payment, or complete |
step.displayName |
String | Label shown in checkout: Select item, Enter details, Make payment, or Complete |
Example step value:
{
"name": "details",
"displayName": "Enter details"
}
send_mode_switch
vaocherapp('send_mode_switch', function (payload) {
console.log(payload.event); // "send_mode_switch"
console.log(payload.mode); // "other" or "self"
console.log(payload.$iframe);
});
| Key | Type | Description |
|---|---|---|
$iframe |
Element | The checkout iframe DOM element that fired this event |
event |
String | Always send_mode_switch |
mode |
String | other (send to someone else) or self (buy for yourself) |
Example: push journey events to the dataLayer
<!-- Make sure to load VaocherApp latest embed script -->
<script type="text/javascript">(function(e,c,a,s){e[s]=e[s]||function(){(e[s].callbacks=e[s].callbacks||[]).push(arguments)};var t=c.createElement("script");t.async=1,t.defer=1,t.src=a,c.head.appendChild(t)})(window,document,"https://vaocher.app/resources/embed/embed.js?v=latest","vaocherapp")</script>
<script type="text/javascript">
window.dataLayer = window.dataLayer || [];
vaocherapp('item_select', function (payload) {
window.dataLayer.push({
event: 'vaocherapp_item_select',
item: payload.item,
});
});
vaocherapp('next_step', function (payload) {
window.dataLayer.push({
event: 'vaocherapp_next_step',
step: payload.step,
});
});
vaocherapp('send_mode_switch', function (payload) {
window.dataLayer.push({
event: 'vaocherapp_send_mode_switch',
mode: payload.mode,
});
});
</script>
Note: Journey events only fire when the checkout form is embedded on your website. They are not sent if the customer opens the hosted checkout link on its own.
If you connect Google Tag Manager inside VaocherApp (Settings > Integrations), checkout can also send events into that container. That is a separate setup from this parent-page JavaScript API. See Track Checkout Actions with Google Tag Manager (GTM).








