How DanubeNet’s Booking Platform Breaks Revenue Tracking (And the GTM Fix That Recovered $66K)

Ishant

Ishant

Published : May 23, 2026 at 5:23 am

Updated : May 30, 2026 at 7:21 am

DanubeNet routes bookings through its own subdomain. GA4 loses the session mid-funnel, Google Ads never sees the conversion, and your reports show a big gap where the revenue should be. We ran into this exact issue managing paid campaigns for a driving school network. After digging into the setup, we recovered $66,143 in booking revenue that had been invisible to every tracking tool they had.

The GTM configuration that fixed it uses three things: cross-domain linking to keep sessions alive, a custom variable that scrapes the booking value off the receipt page when there is no data layer, and a transaction ID to block duplicate conversions. Below is exactly how each piece is built.

What this guide covers

  • How to configure cross-domain linking in GA4 and GTM so sessions survive the jump to DanubeNet
  • A custom JS variable that reads the booking total from the receipt page without a data layer
  • A transaction ID variable to prevent duplicate conversions on page reload
  • How to fire a GA4 purchase event and Google Ads conversion with real booking value

How to set up cross-domain linking so the session survives

First, tell GA4 and Google Ads that your site and the booking platform are one journey. In the GA4 base config tag, the linker domains list every receipt subdomain where the conversion lands:

// GA4 base config tag, linker setting

linker domains:
  receipt.centralmasafety.com,
  receipt.cmscsouthshore.com,
  receipt.cmscdrivingschool.com
In this container, the linker settings sit on the GA4 Google tag, and the Conversion Linker tag fires on every page so the gclid persists in a first-party cookie across the subdomain jump.

The gclid survives the round trip because of how first-party cookies work. When someone lands from a paid click, the Conversion Linker stores the gclid in a _gcl cookie on the root domain. They hop out to DanubeNet to register, then land back on the receipt. subdomain, which shares that root-domain cookie, so the gclid is still there when the conversion fires. The GA4 linker list covers those receipt subdomains so the client ID stays consistent too. One detail decides whether the linker works: in GA4’s Configure your domains screen, set the match type to Contains, not Exactly matches. Exact match silently excludes every subdomain, including the receipt. and register. ones where the money actually changes hands.

From experience: when we audit broken setups, this single match-type toggle is the most common culprit. Everything looks configured, and nothing tracks, because the subdomains were quietly excluded.

How to pull the purchase value off a receipt page with no data layer

This is the part nobody writes about. DanubeNet, like a lot of booking platforms, doesn’t push a tidy ecommerce purchase event you can just read. So instead of hoping for a data layer, we built a variable that tries three sources in order and takes the first real number it finds. Check the data layer, then scrape the receipt’s total from the page itself, then fall back to a URL parameter.

function() {
  try {
    // 1. Data layer, in case the platform does push a value
    if (window.dataLayer) {
      for (var i = window.dataLayer.length - 1; i >= 0; i--) {
        var dl = window.dataLayer[i];
        if (dl.ecommerce && dl.ecommerce.purchase &&
            dl.ecommerce.purchase.actionField &&
            dl.ecommerce.purchase.actionField.revenue) {
          return parseFloat(dl.ecommerce.purchase.actionField.revenue);
        }
        if (dl.value && dl.event === 'purchase') return parseFloat(dl.value);
      }
    }

    // 2. Scrape the total straight off the receipt DOM
    var selectors = ['.order-total', '.total-amount', '.grand-total',
      '[class*="total"]', '[class*="amount"]', '.receipt-total',
      'td.total', '[data-total]'];
    for (var j = 0; j < selectors.length; j++) {
      var el = document.querySelector(selectors[j]);
      if (el) {
        var m = (el.innerText || '').match(/\$?([\d,]+\.?\d{0,2})/);
        if (m) {
          var v = parseFloat(m[1].replace(/,/g, ''));
          if (v > 0) return v;
        }
      }
    }

    // 3. Last resort: read it from the URL
    var p = window.location.href.match(/[?&](?:total|amount|price|value|revenue)=([0-9.]+)/i);
    if (p) return parseFloat(p[1]);
    return 0;

  } catch(e) { return 0; }
}
Custom JavaScript variable: “Receipt Purchase Value”. Returns 0 if nothing’s found, so a misfire never sends a fake number.

Start with the data layer since it is the cleanest source. When it is missing, the DOM scrape reads the total the customer sees on screen. The URL fallback covers platforms that pass the amount as a query parameter. Update the selector list to match your receipt page, then run a real booking through GTM Preview to confirm the right number comes back.

How to build a transaction ID for dedupe when the platform won’t give you one

Receipt pages get refreshed, bookmarked, and revisited. Every reload risks firing the conversion again. A unique transaction ID on every order stops both GA4 and Google Ads from counting the same booking twice. When the platform does not expose one in a clean format, you can derive it from the URL:

function() {
  try {
    var url = window.location.href;
    var patterns = [
      /[?&](?:order_id|orderid|order|transaction_id|txn_id|id)=([a-zA-Z0-9_-]+)/i,
      /\/order[s]?\/([a-zA-Z0-9_-]+)/i,
      /\/receipt\/([a-zA-Z0-9_-]+)/i,
      /\/confirmation\/([a-zA-Z0-9_-]+)/i
    ];
    for (var i = 0; i < patterns.length; i++) {
      var m = url.match(patterns[i]);
      if (m && m[1]) return m[1];
    }
    // Fallback so the field is never empty
    return 'TXN-' + Date.now();
  } catch(e) { return 'TXN-' + Date.now(); }
}
Custom JavaScript variable: "Transaction ID". Prefers the real order number, falls back to a timestamp so dedupe still functions.

Note: the timestamp fallback prevents empty IDs, but a real order number from the URL is far better for deduplication. If the platform doesn't expose it in the URL, check with their support team.

How to fire the GA4 purchase and the Google Ads conversion

With both variables built, the tags are simple. Trigger them on the receipt subdomain, on Window Loaded so the page total has rendered before the value variable reads it.

GA4 purchase event

Tag type: GA4 event

Event name: purchase

Parameters:
  value           = {{Receipt Purchase Value}}
  currency        = USD
  transaction_id  = {{Transaction ID}}

Trigger: Page URL contains receipt.your-site.com (Window Loaded)

Google Ads conversion

Tag type: Google Ads Conversion Tracking

Conversion ID:    AW-XXXXXXXXX
Conversion label: your-label
Conversion value: {{Receipt Purchase Value}}
Order ID:         {{Transaction ID}}
Enhanced conversions: on

Trigger: Page URL contains receipt.your-site.com (Window Loaded)
Conversion ID and label genericized. We run one GA4 event and one Google Ads conversion per property, each scoped to its own receipt subdomain.

Two things make this resilient. The Order ID field is what Google Ads uses to dedupe, so it must carry your transaction ID. And enhanced conversions, switched on here, recover attribution that cookies alone would lose, which matters more every year. If you need a refresher on the value target itself, our guide on calculating break-even ROAS covers where to set it.

What happened after we turned revenue tracking on

Below is the GA4 Traffic Acquisition report for the first three weeks after purchase tracking went live, broken down by channel.

GA4 Traffic Acquisition · May 1 to 21, 2026

$66,143.96 in tracked booking revenue, attributed by channel

87 completed registrations captured as purchase events

$24K+ from paid channels that were previously invisible

For the first time, paid search showed $8,371.79 from 11 bookings and cross-network $15,652.94 from 14, revenue that simply didn't exist in the reports before. Organic search led at $27,843.05, and direct and referral filled in the rest.

GA4 Traffic Acquisition report showing $66,143.96 in total revenue broken down by channel: Organic Search $27,843.05, Cross-network $15,652.94, Paid Search $8,371.79, Direct $8,384.18, Referral $5,892.00

Before this fix, paid search looked like a cost centre because every booking it drove completed on a domain no one was tracking. With attribution restored, paid search showed $8,371.79 from eleven registrations and cross-network added $15,652.94 from fourteen more. That data is what lets value-based bidding actually work: Google Ads can now optimise toward the CDL and adaptive programs that bring in real revenue, not just whatever gets the most clicks. We cover the bidding side of accounts like this in our guide to Google Ads for lead generation.

How to confirm it's actually working before you trust it

A green tag in GTM Preview does not mean the data is correct. Run these three checks with a real test booking before you trust the numbers:

  • GTM Preview: complete a test registration and confirm the purchase tag fires once on the receipt page, with a real number in the value variable.
  • GA4 DebugView: watch the purchase event arrive with value, currency, and a transaction ID populated.
  • Google Ads: check the conversion logs the value within a day or two, and reconcile the count against the platform's own booking total.

The bottom line on tracking booking-platform revenue

Getting the actual booking value into your tracking tools is what lets paid campaigns optimise on revenue instead of clicks. Cross-domain linking keeps the session intact, the DOM fallback reads the total when there is no data layer, and the transaction ID stops duplicate conversions. For this account, putting those three pieces together attributed $66K in bookings to the channels that drove them.

Results after turning on revenue tracking

$66,143 Booking revenue attributed
87 Completed registrations tracked
$24K+ Paid revenue previously invisible
Ishant

Ishant Sharma is the Founder and CEO of Hustle Marketers, a Google Partner digital marketing agency. With 12+ years of experience in Google Ads, Meta Ads, SEO, and e-commerce PPC, he has helped 2500+ brands generate $780M+ in trackable revenue. Upwork Top Rated Plus with 99% Job Success Score. Ishant Sharma is the digital marketing specialist, not the Indian cricketer of the same name.

Frequently Asked Questions

I hope you enjoy reading this blog post. If you want my team to just do your marketing for you, click here.
Scroll to Top