Exposing Revenue Value via dataLayer.push on Thank You Page (for Taboola GTM Tracking)

I’m currently working on setting up accurate revenue tracking for Taboola campaigns via Google Tag Manager. While purchases are being tracked correctly, we’re unable to pass the revenue value into the dataLayer after a successful order, which prevents us from measuring ROAS.

Taboola support has requested that we implement a script to push the revenue value into the dataLayer, ideally on the Thank You page (or wherever the final order total becomes available).

Here’s what I need help with:

  1. How can we expose the final order total on the Thank You page?
  2. Is there a way to use something like dataLayer.push({ event: "purchase", revenue: VALUE }) after the purchase is complete?
  3. If this isn’t natively supported by Funnelish, do you have a recommended workaround or custom JS solution?

For reference, Taboola has already implemented a listener on the Thank You page to pick up the revenue if it becomes available in the dataLayer — we just need that value to be accessible.

Thanks so much in advance for your help!

Hey @Lever, welcome to the community!

Thanks for bringing this up — you’re absolutely on the right track with using dataLayer.push() for Taboola GTM revenue tracking.

We’re actually working on a similar implementation in the background and plan to expose revenue/order data in a more structured way on the Thank You page in an upcoming update.

In the meantime, you can sign up for our newsletter to get notified when it’s released, or feel free to reach out to [email protected] if you’d like to discuss your specific use case further or need a temporary workaround.

Appreciate your patience — great things are coming soon!

@anwerashif any update here ? do we have a way to send order value natively using funnelish.

Hey @Khushal_Rajawat :waving_hand:

Good question — this is still something we are working on to make it more native and structured :+1:

That said, we have already exposed some useful data behind the scenes.

:backhand_index_pointing_right: If you (or your developer) open the browser console on the Thank You page, you will see the Funnelish pay object loaded there.

Inside that object, you can access:

  • Order value

  • Products

  • Customer info

  • Other useful checkout data

You can then use that data to manually push into dataLayer, for example:

dataLayer.push({
  event: "purchase",
  revenue: YOUR_VALUE_HERE
});

Just replace YOUR_VALUE_HERE with the value from the Funnelish object.

So for now:

  • Not fully native yet

  • But data is already available → you can hook into it

If you want, share your setup (GTM / Taboola), I can guide you where exactly to pick the value :+1:

Thank anwerashif

I’m using below code to push data with purchase event to the GTM datalayer.

And, the data received on analytics carry order value as 0 always for all orders. Why is that ?

As per my code it will set the value as 0 for fl_order_value when it’s not found, does fl_order_value becomes availabe a bit later after a purchase has occured ?

<script>
  (function() {
    function ls(key) {
      return localStorage.getItem(key) || undefined;
    }

    window.dataLayer = window.dataLayer || [];
    window.dataLayer.push({ ecommerce: null });

    window.dataLayer.push({
      event: 'purchase',

      ecommerce: {
        transaction_id: ls('fl_order_id'),          // confirm exact key — may be fl_order_id
        value:          parseFloat(ls('fl_order_value')) || 0,
        currency:       ls('fnsh.core.customer.meta.wt:currency'),
        items: [{
          item_name: ls('fl_product_name'),         // confirm key
          item_id:   ls('fl_product_id'),           // confirm key
          price:     parseFloat(ls('fl_order_value')) || 0,
          quantity:  1
        }]
      },

      user_data: {
        email:      ls('fnsh.core.customer.email'),
        first_name: ls('fnsh.core.customer.first_name'),
        last_name:  ls('fnsh.core.customer.last_name'),
        phone:      ls('fnsh.core.customer.phone'),  // confirm if exists

        // Shipping
        address: {
          street:  ls('fnsh.core.customer.shipping_address'),
          city:    ls('fnsh.core.customer.shipping_city'),
          zip:     ls('fnsh.core.customer.shipping_zip'),
          country: ls('fnsh.core.customer.shipping_country')
        },

        // Platform identifiers — already stored by Funnelish
        fbp: ls('fnsh.core.customer.meta.wt:fbp'),  // Meta _fbp
        ttp: ls('fnsh.core.customer.meta.wt:ttp'),  // TikTok _ttp
        ip:  ls('fnsh.core.customer.meta.wt:ip'),
        ua:  ls('fnsh.core.customer.meta.wt:ua'),
        vid: ls('fnsh.core.customer.meta.wt:vid')
      }
    });

  })();
</script>

we don’t have these keys as part of our Client side APIs fl_order_value, fl_product_name, fl_product_id unless you populate them yourself they’d always be empty.

You have two options:

Option 1: Track Purchases Manually (Recommended)

Track what’s being bought (in checkout and upsells) yourself and store its value on those variables, this might be the best options for most cases since it does not rely on undocumented behavior from our client side javascript library.

eg. in Checkout/upsells. track the sales this way:

<script>
// this event gets triggered on checkout purchase attempts (note, it triggers right before processing the purchase, must always check if the purchase went through before tracking).
funnelish.on('of_purchase', (products)=>{
/// store products into localstorage.
// or can calculate amount using something like: products.forEach(p=>{total += p.qty * p.product?.price }
})

// this event gets triggered on upsells/downsells purchase attempts.
funnelish.on('oto_yes', (productId)=>{
/// find the product by Id then get its price/qty.
/// PS. if productId=0 that means the upsells/downsell is using dynamic upsell CTA buttons, in which case you can find the selected product/variants using `funnelish.getSelectedProducts()`.
})
</script>

Must add the code above inside <body>.

The option above might be little tricky but it’s more flexible if you are trying to track something more than just order values.

Option 2: Rely on Facebook Pixel App indirectly

Second option is relying on on of the apps (Google Analytics or Facebook Pixel apps we provide)

Eg. If you are using Facebook Pixel app, then the app stores temporarily the checkout/upsell purchase values inside a localStorage item named funnelish_order_value.

This cookie is only populated after the purchase button is clicked. and then cleared once the next step/page of the funnel is loaded. So the value must be read once in <head> before it’s gone.

We can easily benefit from that by adding this code in <head> HTML of our Upsell/TYP steps:

<script>
let yourOrderTotal = localStorage.getItem("funnelish_order_value")
</script>

Might want to check the localStorage item funnelish_lastPageUrl in which we store the url of the page from which the order value was taken, this insures that you do not accidentally count failed purchases.

order_id we do not store that, but we do have ?activityId parameter which works the same and you can use to identify orders you can recover that by:

let activityId = new URL(window.location).searchParams.get("activityId");

Using this last method the new code becomes like this:

<script>
  (function() {
    function ls(key) {
      return localStorage.getItem(key) || undefined;
    }

    window.dataLayer = window.dataLayer || [];
    window.dataLayer.push({ ecommerce: null });

    // We retrieve the activityId.
    let activityId = new URL(window.location).searchParams.get("activityId");

    // Safety check! making sure the purchase actually went through.
    if (!activityId || funnelish.pageUrl === funnelish_lastPageUrl) return;

    window.dataLayer.push({
      event: 'purchase',

      ecommerce: {
        transaction_id: activityId,          // confirm exact key — may be fl_order_id
        value:          parseFloat(ls('funnelish_order_value')) || 0,
        currency:       ls('fnsh.core.customer.meta.wt:currency'),
        items: [{
          price:     parseFloat(ls('funnelish_order_value')) || 0,
          quantity:  1
        }]
      },

      user_data: {
        email:      ls('fnsh.core.customer.email'),
        first_name: ls('fnsh.core.customer.first_name'),
        last_name:  ls('fnsh.core.customer.last_name'),
        phone:      ls('fnsh.core.customer.phone'),  // confirm if exists

        // Shipping
        address: {
          street:  ls('fnsh.core.customer.shipping_address'),
          city:    ls('fnsh.core.customer.shipping_city'),
          zip:     ls('fnsh.core.customer.shipping_zip'),
          country: ls('fnsh.core.customer.shipping_country')
        },

        // Platform identifiers — already stored by Funnelish
        fbp: ls('fnsh.core.customer.meta.wt:fbp'),  // Meta _fbp
        ttp: ls('fnsh.core.customer.meta.wt:ttp'),  // TikTok _ttp
        ip:  ls('fnsh.core.customer.meta.wt:ip'),
        ua:  ls('fnsh.core.customer.meta.wt:ua'),
        vid: ls('fnsh.core.customer.meta.wt:vid')
      }
    });

  })();
</script>

PS. I’d recommend adjusting the code further to store product names and ids if needed.