Thanx Loyalty Tracking: The Complete GTM and GA4 Guide for Restaurants (2027)

Ishant
Published on October 28, 2026
Ishant
Ishant Sharma is the Founder and CEO of Hustle Marketers, a Google Partner digital marketing agency. Working in Google Ads, Meta Ads, SEO and ecommerce PPC since 2013, he has helped 2,500+ brands generate $780M+ in trackable sales. Upwork Top Rated Plus with 100% Job Success Score. Ishant Sharma is the digital marketing specialist, not the Indian cricketer of the same name.
QUICK ANSWER
Thanx loyalty tracking measures enrollment, reward progress, and redemptions from the Thanx platform by pushing standardized events to the dataLayer, which GTM forwards to GA4. The catch unique to Thanx is that card-linked enrollment completes at payment, not on a sign-up button, so the GA4 sign_up event must fire on the transaction callback. Map Thanx events to GA4 recommended events (sign_up, login, earn_virtual_currency, spend_virtual_currency), tie the Thanx member ID to user_id for lifetime value, and capture card-tokenized purchases server-side with the Measurement Protocol. The universal dataLayer code is below.
Thanx is one of the most data-rich loyalty platforms a restaurant can run. But that is exactly why so many teams track Thanx badly. The platform captures purchase behavior automatically through card linking. As a result, the moments worth measuring, enrollment, reward unlocks, and redemptions, work differently from a normal web form. So if you track Thanx like a standard sign-up flow, you will overcount enrollments. You will also miss redemptions that happen at the counter and never connect a member to their spend.
This guide fixes that. It covers what Thanx actually is and how its two loyalty models work. Then it gives you a correct, copy-paste Thanx loyalty tracking setup for Google Tag Manager and GA4. It also includes the card-linked timing fix that almost every implementation gets wrong. Everything here works alongside your ordering tracking and slots into the same measurement model, so loyalty and orders finally describe the same guest. This October 2026 update adds redemption, expiry and Toast tracking. It also brings a GA4 parameter map and webhook code for in-store purchases.
What does this Thanx loyalty tracking guide cover?
This guide is part of a cluster. The platform-agnostic event reference and GTM build from our former restaurant loyalty tracking guide now live on this page. For ordering events such as add_to_cart and purchase, see our Olo Google Tag Manager tracking guide. Thanx loyalty tracking connects to both through a shared member ID.
On this page
- Quick Discussion
- What is Thanx and how does it work?
- How much are Thanx points worth?
- How do Thanx points earning rules work?
- How does Thanx rewards redemption work, and how do you track it?
- How is Thanx different from other restaurant loyalty platforms?
- Why is tracking Thanx loyalty different from other platforms?
- Which Thanx loyalty events should you track in GA4?
- How do you set up Thanx loyalty tracking with the dataLayer?
- How do you configure GTM for Thanx tracking?
- Should you put Thanx tracking in the same GTM container as Olo?
- How do you add Thanx tracking without breaking your Olo tracking?
- How do you track Thanx through a Toast POS integration?
- How does Consent Mode v2 affect Thanx and Olo tracking together?
- How do you track card-linked enrollment correctly?
- How do you measure Thanx member lifetime value?
- Which Thanx loyalty KPIs belong in your 2027 dashboard?
- How do you build a member versus non-member dashboard in Looker Studio?
- How do you calculate true member lifetime value in BigQuery?
- How do you handle server-side Thanx events?
- Thanx event code generator
- How do you validate Thanx tracking is working?
- What are the most common Thanx tracking mistakes?
- Why choose Hustle Marketers for Thanx tracking?
- Frequently asked questions
Summarize this article with:
Quick Discussion
In short, Thanx loyalty tracking sends Thanx enrollment, reward and redemption events to GA4 through Google Tag Manager. It also sends in-store purchases from your server. This guide also explains what Thanx points are worth and how earning, redemption and expiry work. Finally, it shows how to prove what loyalty members are worth to your restaurant.
- Points value: a Thanx point has no fixed value. Divide a reward’s menu price by its points cost, then compare earn-back rates.
- Enrollment: on card-linked programs it completes at payment, so fire sign_up on the transaction callback, once per member.
- Events: map Thanx actions to sign_up, login, earn_virtual_currency and spend_virtual_currency. Then use the parameter names Google lists.
- Identity: set the non-PII Thanx member ID as user_id in the Google tag settings, but never as an event parameter.
- In-store data: dedupe Thanx purchase webhooks on the purchase id. Then send them with the Measurement Protocol within 72 hours.
- Proof: compare members and non-members on order value, third-visit rate and effective discount rate in Looker Studio or BigQuery.
What is Thanx and how does it work?
Thanx is a guest engagement, loyalty, and CRM platform built for restaurants. Where most loyalty programs rely on punch cards or app check-ins, Thanx is built around credit card tokenization: when a guest links a card, their purchases are tracked automatically with no scanning, no app to open at the counter, and no code to enter. That automatic capture is the whole point, because it produces clean purchase data that powers segmentation and lifecycle marketing rather than just a points balance.
The platform also takes a deliberate stance on rewards. Instead of blanket discounts that erode margin, Thanx leans on access, exclusivity, and personalized perks, the kind of rewards that drive repeat visits without training guests to expect a coupon. For tracking, that distinction matters, because the events you care about are reward unlocks and redemptions tied to real spend, not discount giveaways.
Card-linked loyalty versus check-in loyalty
Thanx offers two enrollment models, and which one a restaurant uses changes how you track it. Card-linked loyalty tracks purchases automatically once a guest registers a payment card, so enrollment and the first purchase often happen in the same moment. Check-in loyalty uses QR codes, phone-number lookup, and native POS integrations, so enrollment is a more visible, discrete action. The tracking code is the same either way, but the firing point differs, and the card-linked model is the one that trips people up, which we cover in detail below.
Thanx’s developer docs add two details that shape your setup. First, each merchant runs only one of the two models. Second, card-linked loyalty is available only in the United States because of card network agreements.
As a result, brands outside the US use check-in loyalty. Meanwhile, card-linked guests who pay cash can still earn by uploading a receipt.
Where does each tracking moment happen in each Thanx model?
This table shows where each tracking moment happens in the two models, so you know where each event can fire. It follows Thanx’s loyalty models guide (checked October 2026).
| Tracking moment | Card-linked program | Check-in program |
|---|---|---|
| Enrollment | Automatic when a guest completes a digital purchase and Thanx tokenizes the card | When the guest gives a phone number or email at the POS, or signs up in the app or online |
| In-store earning | Matched when the guest pays with an enrolled card, or by receipt upload for cash | Recorded when the guest checks in at the POS with staff or on a guest-facing display |
| What the browser can see | Online orders only; in-store card matches happen on the server | Online orders only; POS check-ins happen on the server |
| Where it runs | United States only | Not limited by card network rules, so it suits international brands |
What are the key Thanx features?
CRM & segmentation
ML Winback engine
Lifecycle automation
Access-based rewards
Branded mobile app
The CRM and segmentation tools let you group guests by spend, frequency, and churn risk. The Winback engine uses machine learning to re-engage lapsed guests automatically. Lifecycle automation runs the campaigns that move a guest from first visit to regular. And because credit card tokenization captures purchase data accurately, the segments are built on real behavior rather than self-reported preferences. Each of these features generates signals worth tracking, but the highest-value ones for analytics are enrollment, reward redemption, and the spend tied to a member.
What integrations does Thanx support?
Thanx integrates natively with the major ordering and POS systems restaurants already run, including Olo, Toast, Square, and Deliverect. With Olo specifically, loyalty enrollment can happen directly inside online ordering, and a large share of digital purchasers get enrolled into the CRM automatically at checkout. For tracking, these integrations matter because the enrollment and purchase events you want to measure often originate inside the ordering flow, which means your Thanx loyalty tracking and your ordering tracking need to share one consistent measurement model.
How much are Thanx points worth?
Thanx does not publish a fixed value for a point. Each restaurant brand sets up its own program in Thanx, including how many points a dollar earns, which rewards sit in the rewards marketplace and how many points each reward costs, so a point is worth whatever that brand’s reward menu makes it worth.
Thanx’s own guidance gives “$1 = 1 point, or $1 = 10 points” as example conversion rates and says both ratios deliver the same economic value. The higher ratio simply feels faster to guests, which Thanx says suits lower-check concepts. That means the number of points on your balance tells you very little until you compare it with the reward prices.
How do you work out what Thanx points are worth?
Divide the menu value of a reward by the points it costs. That gives you the value of one point. Multiply it by the points you earn per dollar and you get your earn-back rate, the share of each dollar you get back if you redeem everything.
- Find the brand’s earn rate in its app or rewards terms, for example 10 points per $1.
- Pick a reward in the rewards marketplace and note its points cost.
- Divide the reward’s menu price by its points cost to get the value per point.
- Multiply the value per point by the points earned per $1 to get the earn-back rate.
- Read the reward’s fine print, because an activated reward can expire and only one reward applies at a time.
The three programs below are made-up examples that show the math. They are not any real brand’s rules.
| Example program | Points per $1 | Reward and points cost | Value per point | Earn-back rate |
|---|---|---|---|---|
| Program A | 1 | $5 reward for 100 points | $0.05 | 5% |
| Program B | 10 | $5 reward for 1,000 points | $0.005 | 5% |
| Program C | 10 | $12 entree for 4,000 points | $0.003 | 3% |
Programs A and B show what Thanx means by equal economic value: ten times the points, ten times the price, the same 5% back. Program C gives back less per dollar, even though its balance grows just as fast as Program B’s.
From the restaurant’s side, Thanx tracks the real cost as the effective discount rate. Thanx says a healthy rate is 3% or below for most well-run programs, that legacy loyalty platforms commonly run at 10% to 12%, and that Thanx brands average 2% to 2.5%. The effective rate usually sits below the earn-back rate, because not every guest redeems every point.
How do Thanx points earning rules work?
Guests earn Thanx points automatically when they make a tracked purchase, with no card scanning or manual check-in needed on card-linked programs. Brands can also grant bonus points through campaigns, intro offers, birthday rewards and tiers, and guests spend points on rewards in the brand’s rewards marketplace.
The exact rules are set by each brand, so treat the table below as the framework Thanx’s documentation describes, then check the brand’s own rewards terms for its numbers.
| Rule | What Thanx documents | What to check in the brand’s terms |
|---|---|---|
| Earning on purchases | Points are collected automatically on tracked purchases; check-in programs can use options such as scanning a QR code in store | Points per dollar and which order channels count |
| Bonus points | Welcome bonuses, birthday rewards and campaign bonuses, such as points for trying new menu items or for guests who have not visited recently | Which bonuses are running and when they end |
| Redeeming points | Guests check their balance and exchange points for rewards in the marketplace, which can include discounts, experiences, early access and partner perks | The points cost of each reward |
| Not enough points | A reward that costs more points than the guest has shows as Locked | How many points you need for the reward you want |
| Using a reward | Depending on the reward type, the guest activates it and it applies to the next purchase; only one reward applies at a time | Whether the reward works in store, online or both |
| Reward timer | An activated reward expires when its countdown reaches zero, with 1 hour as Thanx’s standard interval | The timer the brand uses |
| Refunds | If an order is voided or refunded, the reward goes back to the guest’s account | Nothing extra, this is handled automatically |
| Tiers | Programs have 3 tiers, and Thanx notifies guests when they are $100 away from the next tier and again when they reach it | Tier names and what each tier unlocks |
| Points expiry | Thanx’s published guides do not set one universal expiry rule for points | The brand’s expiry policy, if it has one |
How do these rules map to your tracking?
Each rule above maps to an event already in this guide’s dataLayer code, so you can measure the program the way guests actually use it.
| Guest action | dataLayer event in this guide | GA4 event |
|---|---|---|
| Earns points on a purchase or bonus | thanx_reward_earned with points_value | earn_virtual_currency |
| Redeems a reward | thanx_reward_redeemed with reward_value | spend_virtual_currency |
| Moves up a tier | set_loyalty_user with the new loyalty_tier | User property update |
| Gets a reward back after a refund | Handle server side, since it happens after the order | Measurement Protocol event |
Bonus points granted after an in-store visit happen without a browser, so send them from your backend as covered in the server-side section below. Our guide to server-side tracking for restaurants covers the setup in more detail.
Which part of the bill earns Thanx points?
For orders sent through Thanx’s Loyalty API, Thanx calculates points from the payment amount. In other words, Thanx defines it as the subtotal plus tax minus discounts.
Tips do not earn points. Also, loading a gift card does not count as a purchase, although paying with a gift card does. Finally, Thanx creates the purchase and adds the points only when the order reaches its billed state.
These rules come from Thanx’s basket lifecycle guide for integration partners (checked October 2026). Each brand then applies its own points per dollar to that amount. For tracking, this means points_value belongs after payment, never on the cart total while a guest is still ordering.
When do Thanx points, rewards and tier status expire?
Whether Thanx points expire depends on the brand. Thanx’s Loyalty 3.0 announcement says brands configure their own points expiration date. Likewise, its Rewards Marketplace article says marketers can set expiration dates for points and rewards. Rewards, activated rewards and tier status also run on their own clocks, as shown below.
| What expires | When it expires | Where the rule comes from |
|---|---|---|
| Points balance | On the date the brand sets, if it sets one | The brand’s loyalty terms |
| A reward in the guest’s account | On the expiration date shown in the reward details | The campaign or reward settings |
| An activated in-store reward | When its countdown ends, 1 hour as Thanx’s standard, or when staff tap Mark as used | Thanx’s consumer loyalty best practices |
| Tier status | 12 months after the date the guest reaches the tier; spending progress resets each January 1 | Thanx’s guest tier program guide |
In your reports, expired value counts as breakage, that is, rewards earned and never redeemed. Thanx says breakage is part of the points model and helps keep the effective discount rate low. So read it from the gap between earn_virtual_currency and spend_virtual_currency instead of firing a separate expiry event.
How does Thanx rewards redemption work, and how do you track it?
Thanx rewards redemption runs through five routes. Guests can redeem in the online cart, with an in-store tap and countdown timer, or with an in-store code. They can also get automatic cash back on the next purchase. Finally, the POS can find the guest by phone or email and apply a reward.
However, only the online route happens in a browser, so each route needs its own capture point in your tracking. The table below shows how each route works, based on Thanx’s consumer loyalty best practices (checked October 2026).
| Redemption route | What happens | Browser sees it? |
|---|---|---|
| Online cart | Available rewards show in the cart and the guest applies one; only one reward can apply at a time | Yes |
| In store, no code | The guest taps Redeem, a countdown starts (1 hour as standard) and staff fulfill the reward | No |
| In store, with code | The app shows a code, bar code or QR code that staff key into the POS | No |
| Automatic cash back | The guest activates the reward and it applies to the next purchase as a statement credit, with no timer | No |
| POS lookup | With Toast in-store redemption, staff or a guest-facing display finds the guest by phone or email and applies a reward | No |
Which Thanx redemptions can you track in the browser?
In short, fire spend_virtual_currency from the browser only for the online cart. Instead, send the other routes through the server-side setup further down. You can feed them from your POS integration or Thanx’s data exports. Otherwise, reconcile them against Thanx’s redemption report.
Hidden menus and access passes are non-discount rewards with their own flows. For example, a hidden menu unlocks extra items in the app. Likewise, a guest shows an access pass to a server in store.
What is the Thanx reward catalog?
The Thanx reward catalog is the Rewards Marketplace: the menu of rewards a brand offers in exchange for points. It can include discount rewards, such as dollars off or free items. It can also include non-discount perks, such as experiences, early access and partner perks. In addition, brands can add rewards or change their points cost at any time from the Thanx dashboard.
Because catalog prices can change, send reward_name as item_name on spend_virtual_currency so redemptions group by reward. Also, note the date whenever a brand reprices one. That date matters, because a repriced reward changes the value per point you worked out in the points section above.
When should a Thanx redemption event fire on an online order?
Fire spend_virtual_currency after the order reaches the billed state, not when the guest applies the reward in the cart. In Thanx’s basket lifecycle, the checkout state only checks which rewards apply. Then the placed state locks the reward for about 2 days. Finally, the billed state creates the purchase, adds the points and marks the reward used.
| Basket state | What Thanx does | What to send to GA4 |
|---|---|---|
| checkout | Checks reward eligibility and returns the discount | Nothing yet; the guest can still change the order |
| placed | Locks the reward for about 2 days and deducts points for a points product | Nothing yet, unless payment is captured at the same moment |
| billed | Creates the purchase, adds points and marks the reward used | spend_virtual_currency and earn_virtual_currency, next to your ordering platform’s purchase |
| voided | Restores the locked reward and returns points spent on a points product | No loyalty event; Thanx reverses it automatically |
| refunded | Restores the reward and claws back the points earned on that purchase | Your ordering platform’s refund event, if it sends one; reconcile loyalty in Thanx |
Most restaurants never send these states themselves, because the ordering platform does. Instead, the closest moment you can see in the browser is the order confirmation callback after payment succeeds. So fire there, then compare GA4 with Thanx’s redemption report each week, as the validation section describes.
How is Thanx different from other restaurant loyalty platforms?
Knowing where Thanx sits helps you track it correctly, because the differences are behavioral, not just feature lists.
| Platform | Enrollment model | Best for |
|---|---|---|
| Thanx | Card-linked or check-in | CLV growth without discounting |
| Punchh | App and account based | Large enterprise chains |
| Paytronix | Account and card based | Data-heavy enterprise programs |
| Square Loyalty | Phone-number based | Smaller independents on Square |
| Toast Loyalty | Card linked, POS native | Restaurants already on Toast POS |
The takeaway for tracking: Thanx and Toast both use card-linked enrollment. That means enrollment completes at payment rather than on a click. Square, by comparison, uses phone-number enrollment, which is a discrete action. Recognizing which model you run tells you exactly where to fire the enrollment event. In fact, getting that wrong is the single most common Thanx tracking error.
Why is tracking Thanx loyalty different from other platforms?
Card-linked enrollment fires at payment, not on a button
With a normal loyalty program, a guest clicks “join,” you fire a sign_up event, done. However, Thanx card-linked loyalty does not work that way. Enrollment completes when the guest pays with a registered card, which can be seconds or minutes after any button click. Sometimes there is no sign-up button at all, because enrollment happens automatically at checkout. If you fire sign_up on a button, you count intentions, not enrollments. As a result, your number will never reconcile with the Thanx dashboard.
The fix is to fire the enrollment event on the transaction-complete callback, the same place you confirm the purchase. And because Thanx can auto-enroll a large share of digital purchasers, you also need to dedupe. In other words, fire sign_up only on a guest’s first qualifying purchase, not on every order. Both fixes are in the code below.
There is also a second difference. Thanx captures purchase data through card tokenization on the server side. In addition, some loyalty events happen after the browser session has ended. For example, a reward can unlock after a qualifying visit, or a guest can redeem at the physical counter. As a result, a client-side dataLayer push cannot capture those at all. They need server-side tracking, which we cover further down.
Which Thanx loyalty events should you track in GA4?
The same recommended-event mapping that works for any loyalty program works for Thanx. Using recommended events instead of custom ones also gives you GA4 reporting for free. Thanx reward progress behaves like an in-app currency, so it maps cleanly to GA4’s virtual-currency events.
| Thanx action | dataLayer event | GA4 event | Fires when |
|---|---|---|---|
| Enrollment | thanx_signup | sign_up | First card-linked purchase |
| Member sign-in | thanx_login | login | App or web sign-in |
| Reward unlocked | thanx_reward_earned | earn_virtual_currency | Threshold reached |
| Reward redeemed | thanx_reward_redeemed | spend_virtual_currency | Reward applied to an order |
| Member purchase | purchase | purchase + user_id | Any member order |
Which GA4 parameters does each Thanx event need?
Each Thanx event needs its dataLayer fields mapped to the parameter names Google lists for that event. Google’s recommended events reference (checked October 2026) makes value and virtual_currency_name required on spend_virtual_currency. In contrast, method on sign_up and login and both earn_virtual_currency parameters are optional but worth sending.
Use this table when you fill in the event parameters on each GA4 Event tag in GTM.
| GA4 event | GA4 parameter | Required by Google? | dataLayer field in this guide |
|---|---|---|---|
| sign_up | method | No | loyalty_method |
| login | method | No | loyalty_method |
| earn_virtual_currency | virtual_currency_name | No | points_currency_name |
| earn_virtual_currency | value | No | points_value |
| spend_virtual_currency | virtual_currency_name | Yes | points_currency_name |
| spend_virtual_currency | value | Yes | reward_value |
| spend_virtual_currency | item_name | No | reward_name |
| Any loyalty event | loyalty_tier, loyalty_program | Custom; register as event-scoped custom dimensions | loyalty_tier, loyalty_program |
- Keep the member ID out of event parameters. Google’s User-ID guide says user_id is a configuration setting. So read loyalty_id into the user_id field of the Google tag settings. Never put it in an event parameter, user property or custom dimension. Also, send null when a member signs out, never an empty string.
- Stay inside GA4’s limits. For example, event and parameter names can run to 40 characters and parameter values to 100. Likewise, user property names can run to 24 characters and their values to 36. In addition, User-ID values can run to 256 characters, and a standard property allows 25 parameters per event.
- Spend custom dimensions once. A standard property gets 50 event-scoped and 25 user-scoped custom dimensions. So register loyalty_tier, loyalty_program and the loyalty_member user property once, then reuse them on every event.
How do you set up Thanx loyalty tracking with the dataLayer?
This is the universal layer, written for the Thanx firing points. It is also plain JavaScript with no dependencies. Call each function from the right Thanx callback, which for card-linked enrollment means the transaction-complete handler, not a button click.
// ============================================================
// Thanx Loyalty dataLayer for GTM + GA4
// No dependencies. Fire from the correct Thanx callbacks.
// ============================================================
window.dataLayer = window.dataLayer || [];
// 1. ENROLLMENT -> GA4 sign_up
// IMPORTANT: call this on the TRANSACTION-COMPLETE callback for a
// guest's FIRST qualifying purchase, not on a sign-up button.
// isFirstPurchase prevents double-counting auto-enrolled guests.
function trackThanxSignup(memberId, isFirstPurchase) {
if (!isFirstPurchase) return; // dedupe: only the first time
window.dataLayer.push({
event: 'thanx_signup',
loyalty_method: 'card_linked',
loyalty_program: 'Thanx',
loyalty_id: memberId // non-PII Thanx member ID
});
}
// 2. MEMBER SIGN-IN -> GA4 login
function trackThanxLogin(memberId) {
window.dataLayer.push({
event: 'thanx_login',
loyalty_method: 'thanx',
loyalty_program: 'Thanx',
loyalty_id: memberId
});
}
// 3. REWARD UNLOCKED -> GA4 earn_virtual_currency
function trackThanxRewardEarned(rewardName, progressValue, tier) {
window.dataLayer.push({
event: 'thanx_reward_earned',
points_currency_name: 'thanx_reward',
points_value: progressValue, // e.g. 1 reward, or $ progress
reward_name: rewardName, // 'Free Entree'
loyalty_tier: tier
});
}
// 4. REWARD REDEEMED -> GA4 spend_virtual_currency
function trackThanxRewardRedeemed(rewardName, rewardValue, tier) {
window.dataLayer.push({
event: 'thanx_reward_redeemed',
points_currency_name: 'thanx_reward',
reward_value: rewardValue, // value applied to the order
reward_name: rewardName,
loyalty_tier: tier
});
}
// 5. MEMBER IDENTITY -> set once on sign-in / page load
// Lets GA4 attribute every purchase to the member for LTV.
function setThanxMember(memberId, tier) {
window.dataLayer.push({
event: 'set_loyalty_user',
loyalty_id: memberId, // also set as GA4 user_id
loyalty_member: true,
loyalty_program: 'Thanx',
loyalty_tier: tier
});
}Never use a phone number or email as the Thanx member ID. GA4 prohibits personally identifiable information. Thanx uses card tokenization, so use the tokenized or internal member identifier it exposes, never the raw card, phone, or email. If you only have a phone number, hash it server-side first.
How do you configure GTM for Thanx tracking?
The GTM side is identical to any loyalty setup, because the container listens for event names rather than anything Thanx-specific. You need one Constant variable for your GA4 Measurement ID and Data Layer Variables for the loyalty fields. You also need Custom Event triggers for each Thanx event and GA4 Event tags that forward each one.
There is no separate file to import. Instead, the vendor-neutral container from our former restaurant loyalty tracking guide now lives on this page as the build below. To begin with, set your Measurement ID in a single Constant variable. Then add a Data Layer Variable for each loyalty field. Finally, point one Custom Event trigger at each Thanx event name. The mapping is one trigger per event:
| Trigger (Custom Event) | Fires GA4 tag |
|---|---|
| thanx_signup | GA4: sign_up |
| thanx_login | GA4: login |
| thanx_reward_earned | GA4: earn_virtual_currency |
| thanx_reward_redeemed | GA4: spend_virtual_currency |
If you would rather keep Thanx fully self-contained, duplicate each tag and trigger in that container. Then rename the trigger event names to the thanx_ versions above. Either way, set the GA4 user_id field on your Google Tag to the Thanx member ID variable so member attribution works.
Should you put Thanx tracking in the same GTM container as Olo?
Yes, in almost every case. Keep loyalty and Olo tracking in one container. Then build the loyalty tags in the same workspace as your Olo tags. One container means one source of truth and one set of shared variables. It also means one consent configuration and one place to debug when something fires twice. This also makes the collisions in the next section easy to see. After all, every tag and trigger sits in the same workspace.
A second container is the wrong default. For one thing, it loads a second gtm.js on the page. That is the fastest way to end up with duplicate page_views and double-fired events. It also splits your debugging across two interfaces. You only genuinely run two containers when your Olo ordering lives on an Olo-hosted domain with its own container. In that case the split is unavoidable. So you stitch the two sides together with cross-domain measurement and a shared member ID, exactly as described below. For everything else, one merged container is cleaner and safer.
How do you add Thanx tracking without breaking your Olo tracking?
This is the part most advertisers and analytics teams get wrong. Worse, it quietly corrupts data for months before anyone notices. Your Olo setup already fires a complete GA4 ecommerce sequence, including a purchase event with revenue. So if you bolt loyalty tracking on top carelessly, you double-count revenue, inflate users, or split one guest into two. Here are the five collisions and how this setup avoids each one.
1. Never fire a second purchase event
Olo already fires purchase with the order revenue. If you add your own purchase event to attach loyalty data, you count every order twice. As a result, your GA4 revenue doubles. Do not send a loyalty purchase. Instead, attach the member identity to the order Olo already tracks. To do that, set user_id and the loyalty_member user property at the configuration level. Then they ride along on Olo’s existing purchase automatically.
2. Do not import a second GA4 configuration
If your container already initializes GA4 for Olo, adding a second Google Tag or GA4 configuration fires page_view twice. In turn, that inflates users and sessions. Build the loyalty tags with no configuration tag of their own. Instead, their GA4 Event tags use measurementIdOverride, the Measurement ID field on the tag. As a result, they ride on the GA4 you already load for Olo. Only add a Google Tag if the site has no GA4 base at all, and then add exactly one.
How do you keep Thanx and Olo data clean across tags and domains?
3. Use the same Measurement ID as Olo
Loyalty events must send to the same GA4 property as your Olo orders. So point the Const GA4 Measurement ID variable at the exact ID Olo uses. Otherwise, a different ID puts orders in one property and loyalty in another. Then you can never join member lifetime value because the two halves live in separate datasets.
4. Keep sendEcommerceData set to false on every loyalty tag
Olo populates a GA4 ecommerce object on the page. If a loyalty tag has sendEcommerceData set to true, a sign_up or earn_virtual_currency event scoops up Olo’s cart items. It then attaches them to the wrong event, which corrupts both the loyalty data and the ecommerce reports. So leave it set to false on every loyalty tag you build.
5. Stitch across domains if Olo ordering is Olo-hosted
If your Olo ordering runs on an Olo-hosted domain rather than embedded on your site, guests cross between two domains. Each guest enrolls and browses loyalty on your main domain but pays on the Olo domain. Without cross-domain configuration, GA4 sees two different users and member lifetime value falls apart, while users inflate. Add both domains to your GA4 data stream under configure your domains. Then pass the same non-PII member ID as user_id on both sides so the journey stitches into one guest.
Which safeguards keep Thanx and Olo events apart?
Two structural safeguards make this work. First, every loyalty trigger is a Custom Event set to EQUALS on an exact event name. As a result, a loyalty tag can never fire on one of Olo’s ecommerce events. Likewise, an Olo tag can never fire on a loyalty event. Second, every loyalty dataLayer push includes all of its own parameters instead of reusing values from a previous push. This prevents a loyalty event from reading a stale revenue or currency value that Olo set earlier in the session. Keep both habits and the two systems run side by side cleanly.
The one-screen test: open GA4 DebugView and complete one real order as a logged-in member. You should see exactly one purchase, one set of loyalty events, one page_view per page, and a populated user_id. If you see two purchases or two page_views, you have a duplicate config or a second purchase event. In fact, these are the two most common ways loyalty tracking breaks Olo tracking.
How do you track Thanx through a Toast POS integration?
Thanx connects to Toast as a Toast partner integration. Toast shares in-store transaction data with Thanx, and Thanx then links each purchase to a guest profile. As a result, none of that passes through a browser.
GA4 sees Toast in-store loyalty activity only if you send it server-side. Meanwhile, your website and online ordering keep the client-side setup in this guide.
Toast’s support article on the integration says Thanx builds mobile and web ordering on top of Toast’s online ordering. According to that article, Thanx also enrolls those guests in the loyalty program automatically and registers their cards. So Thanx can recognize their later purchases, both in store and online. To switch the integration on:
- Add Thanx in Toast Web. Your restaurant needs access to Toast Partner Integrations. Once it has access, go to Integrations, then Integrations management, then Browse and purchase integrations. Then search for Thanx and select Add Now.
- Accept the data scope terms. Review them, then select Confirm. After that, the Thanx onboarding team contacts you, and Toast says onboarding can take up to four weeks.
- Map locations. Agree with Thanx how each Toast location appears in Thanx, also covering franchise or multi-entity cases.
- Test the data flow. Run test transactions and confirm the expected fields arrive in Thanx, then pilot a few locations before you roll out.
Which Toast moments can reach GA4?
Only online orders placed through Thanx ordering on Toast reach the browser. The other Toast moments need a server-side send, or you count them in Thanx instead.
Thanx’s Toast guide (checked October 2026) says the integration typically shares transaction totals with item and modifier SKUs. It also shares location identifiers, guest identifiers such as phone and email, and discount or tender indicators. However, the exact mappings depend on your Toast setup.
| Toast moment | Reaches the browser? | How to measure it |
|---|---|---|
| Online order through Thanx ordering on Toast | Yes | The dataLayer events in this guide, fired on the order confirmation callback |
| In-store purchase by an enrolled guest | No | Thanx purchase webhook to the Measurement Protocol; in-store purchases arrive with an empty order field |
| Loyalty sign-up at the POS by phone or email | No | Count it in Thanx; send a server-side sign_up only if you hold that guest’s GA4 client_id |
| Reward applied through the POS | No | Reconcile with Thanx’s redemption report, or send it server-side from your POS data |
If your main website runs on Toast Websites, Toast offers a Google Tag Manager ID field. You will find it under Toast Web, Websites, Settings and Integrations. However, Toast says the field is unavailable for customers in Australia, Canada, Ireland and the UK.
When the website and ordering sit on different domains, set up cross-domain measurement as our GA4 cross-domain tracking guide explains. As a result, one guest stays one user.
How does Consent Mode v2 affect Thanx and Olo tracking together?
If your restaurant serves guests in the EEA or the UK, Consent Mode v2 is not optional. You also have to apply it consistently across both your loyalty tags and your Olo tags. The failure mode is subtle. Suppose your Olo tags wait for analytics consent, but your loyalty tags fire regardless. In that case, you collect loyalty events for guests who never appear in your ordering data. Your member-versus-non-member comparison then ends up built on two different consent populations.
The fix is to treat both sets of tags the same way. Set your consent defaults to denied before GTM loads. Then update them when the guest makes a choice through your consent banner. Also make sure every loyalty tag requires analytics_storage just like your Olo tags do. Finally, give the loyalty tags the same Additional Consent Checks setting in Tag Manager as your Olo tags. That way, they follow your container’s additional consent checks rather than overriding them. As a result, loyalty and ordering stay on the same consent logic.
For US-only restaurants this matters less, but aligning consent behavior across both tag sets is still good practice. That way, your loyalty and ordering data describe the same guests rather than two overlapping but different groups.
How do you track card-linked enrollment correctly?
This is the section that separates an accurate Thanx setup from a misleading one. Card-linked enrollment has two traps, but both have clean fixes.
The first trap is timing. Because enrollment completes at payment, the sign_up event has to fire from your transaction-complete handler. That is the same callback where you confirm the order succeeded. Firing on a “join now” button counts guests who started but never paid, inflating enrollment.
The second trap is auto-enrollment. Thanx can enroll a large share of digital purchasers automatically at checkout. So a sign_up could fire on every single order if you are not careful. The fix is the isFirstPurchase guard in the code above. In other words, pass true only on a guest’s first qualifying purchase, which your backend or Thanx response can tell you. That way, enrollment fires once per member. After that, every order counts as a purchase, not a new sign-up.
Reconciliation check: after a week, compare your GA4 sign_up count to the new-member count in the Thanx dashboard. If GA4 is higher, you are still firing on intent or on repeat purchases. If they line up, your card-linked enrollment tracking is correct.
How do you measure Thanx member lifetime value?
Thanx exists to grow customer lifetime value, so your tracking should prove whether it is working. The mechanism is the same as any loyalty program. Set the GA4 user_id to the non-PII Thanx member ID, then attach a loyalty_member user property to member sessions. Once you set user_id, GA4 stitches a member’s activity across devices into one identity. You can then build a members-versus-non-members comparison.
Combined with the purchase events from your ordering setup, this answers the question that justifies the Thanx investment. Do Thanx members spend more per order and visit more often than non-members? Because Thanx captures purchase data through card linking, the member side of that comparison is unusually complete. As a result, the LTV analysis is more reliable than it would be with a check-in program that misses offline visits.
Which Thanx loyalty KPIs belong in your 2027 dashboard?
Track six numbers: member share of sales, enrollment rate, third-visit rate, redemption rate, effective discount rate and member versus non-member order value. Together they show whether the program changes behavior or just gives away margin.
| KPI | How to calculate it | Where the data comes from |
|---|---|---|
| Member share of sales | Member revenue divided by total revenue | GA4 purchase events split by loyalty_member |
| Enrollment rate | New members divided by unique purchasers in the period | sign_up count and purchasers in GA4, checked against Thanx |
| Third-visit rate | Members with 3 or more purchases divided by all members | BigQuery export, using the query in this guide |
| Redemption rate | Rewards redeemed divided by rewards earned | spend_virtual_currency and earn_virtual_currency counts |
| Effective discount rate | Value of redeemed rewards divided by member sales | reward_value totals and member revenue |
| Member vs non-member order value | Revenue divided by purchases for each segment | The Looker Studio comparison table |
Two benchmarks from Thanx help you read the results. Thanx says guests who make a third purchase are roughly 12 times more valuable over their lifetime than first-time visitors. Thanx bases that figure on data from quick service programs. That is why the third-visit rate earns its place. In addition, its 3% or below guidance gives you a ceiling to watch for the effective discount rate. If your orders run through Toast, our Toast POS guide explains how its own reporting splits discounts from net sales.
If the member numbers in GA4 look inflated, check for doubled purchase events with our guide to fixing GA4 duplicate purchases before you trust any loyalty KPI.
What does a Thanx KPI scorecard look like with example numbers?
A worked scorecard turns the six KPIs into one monthly view. For example, the table below uses invented figures for one month at a fictional restaurant group. These figures only show the math, so they are not benchmarks or client results.
| KPI | Example inputs | Result | How to read it |
|---|---|---|---|
| Member share of sales | $60,000 member revenue of $150,000 total | 40% | Members drive a large share of sales |
| Enrollment rate | 400 new members from 4,000 unique purchasers | 10% | One in ten purchasers joined |
| Third-visit rate | 540 of 1,800 members with 3 or more orders in 120 days | 30% | Watch the trend, since Thanx ties the third purchase to long-term value |
| Redemption rate | 600 rewards redeemed of 900 earned | 67% | The other 33% is breakage so far |
| Effective discount rate | $1,500 of redeemed rewards on $60,000 member sales | 2.5% | Under the 3% ceiling Thanx recommends |
| Order value, members vs non-members | $60,000 over 2,000 member orders vs $90,000 over 3,750 other orders | $30 vs $24 | Members spend $6 more per order in this example |
However, if the effective discount rate in your own scorecard climbs above 5%, Thanx suggests auditing the reward structure. Then set member lifetime value against what it costs to win a new guest. Our customer acquisition cost guide walks through that calculation.
How do you build a member versus non-member dashboard in Looker Studio?
When the events flow and user_id is in place, Looker Studio shows the comparison that justifies the loyalty spend. The whole dashboard hinges on one dimension: loyalty_member, the user property you registered as a custom dimension in GA4. Then break any metric by that dimension to see members and non-members side by side.
The setup
Connect Looker Studio to your GA4 property as the data source. Then confirm that loyalty_member, loyalty_tier, and loyalty_program show up as available dimensions. If they do not, you never registered them as custom dimensions in GA4, so go back and register them first. Then build three things: scorecards, a comparison table, and a tier breakdown.
| Chart | Dimension | Metrics |
|---|---|---|
| Comparison table | loyalty_member | Total revenue, Total users, Purchases, Average purchase revenue |
| Tier breakdown | loyalty_tier | Total revenue, Purchases, Average purchase revenue |
| Engagement scorecards | loyalty_member | sign_up, earn_virtual_currency, spend_virtual_currency counts |
For purchase frequency, add a calculated field that divides Purchases by Total users. This gives you orders per guest for each segment. Likewise, for average order value, use Average purchase revenue or divide Total revenue by Purchases. Then lay members and non-members next to each other. The gap in order value and frequency tells you whether the loyalty program is actually changing behavior.
Looker Studio reads GA4’s aggregated, session-scoped data. That is fine for a directional comparison, but it carries GA4’s sampling and cardinality limits. For exact lifetime value across a guest’s entire history, calculate it in BigQuery instead, as the next section shows.
How do you calculate true member lifetime value in BigQuery?
GA4’s interface tops out at session-level comparison. For real lifetime value, the revenue a member generates across their entire history, you need the GA4 BigQuery export. It can run in the free BigQuery sandbox until you pass its limits. After that, BigQuery charges apply. Also, Google’s Analytics Help (checked October 2026) caps the daily export at 1 million events a day on standard properties. Enable it under GA4 Admin, then BigQuery links. After a day of data, the query below gives you member versus non-member lifetime value directly.
-- Member vs non-member lifetime value from the GA4 BigQuery export.
-- Replace your_project.analytics_XXXXXX with your dataset, and set the dates.
WITH purchases AS (
SELECT
user_pseudo_id,
user_id,
(SELECT value.string_value
FROM UNNEST(user_properties)
WHERE key = 'loyalty_member') AS loyalty_member,
IFNULL(ecommerce.purchase_revenue, 0) AS revenue
FROM `your_project.analytics_XXXXXX.events_*`
WHERE event_name = 'purchase'
AND _TABLE_SUFFIX BETWEEN '20260101' AND '20261231'
),
per_guest AS (
SELECT
COALESCE(user_id, user_pseudo_id) AS guest,
MAX(loyalty_member) AS loyalty_member,
COUNT(*) AS orders,
SUM(revenue) AS lifetime_revenue
FROM purchases
GROUP BY guest
)
SELECT
CASE WHEN loyalty_member = 'true' THEN 'Member' ELSE 'Non-member' END AS segment,
COUNT(*) AS guests,
ROUND(AVG(lifetime_revenue), 2) AS avg_lifetime_value,
ROUND(AVG(orders), 2) AS avg_orders_per_guest,
ROUND(SAFE_DIVIDE(SUM(lifetime_revenue), SUM(orders)), 2) AS avg_order_value
FROM per_guest
GROUP BY segment;The query pulls every purchase and reads each guest’s loyalty_member status from the user properties. It then rolls revenue up per guest, using user_id where it exists and the pseudonymous ID otherwise. Finally, the query splits guests into members and non-members. For each group, it reports average lifetime value, orders per guest, and average order value. That is the definitive answer to whether Thanx members are worth more. It draws on full history rather than a single session window. It is also the number worth putting in front of an owner deciding whether the loyalty investment pays off.
This only works if you set user_id correctly and keep it PII-free, which is why the identity setup earlier matters. The member ID stitches a guest’s orders together across sessions and devices. Otherwise, this query measures sessions, not guests.
How do you calculate the Thanx third-visit rate in BigQuery?
Count each member’s orders in the GA4 BigQuery export over a 120-day window. Then divide the members with three or more orders by the members with at least one. The 120 days follow Thanx’s guidance, since it aims to get guests to a third purchase within 120 days.
BigQuery SQL, member third-visit rate (copy and paste)
/* Third visit rate for Thanx members from the GA4 BigQuery export.
Replace your_project.analytics_XXXXXX with your dataset.
The window covers 120 days and skips the last 3, which can still change. */
WITH member_orders AS (
SELECT
user_id,
COUNT(DISTINCT ecommerce.transaction_id) AS orders
FROM `your_project.analytics_XXXXXX.events_*`
WHERE event_name = 'purchase'
AND user_id IS NOT NULL
AND _TABLE_SUFFIX BETWEEN
FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 122 DAY))
AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 3 DAY))
GROUP BY user_id
)
SELECT
COUNT(*) AS members_with_an_order,
COUNTIF(orders >= 3) AS members_with_3_plus_orders,
ROUND(100 * SAFE_DIVIDE(COUNTIF(orders >= 3), COUNT(*)), 1) AS third_visit_rate_pct
FROM member_orders;The query skips the latest three days because those daily export tables can still change. Google keeps updating each table for up to two calendar days after its date, plus the current day. During that window, late events such as Measurement Protocol hits arrive.
GA4 also sees only members who placed a tracked order. So compare the result with Thanx’s own member count before you report it.
How do you handle server-side Thanx events?
Card-tokenized purchases need the Measurement Protocol
Thanx tracks card-linked purchases server-side. Rewards can also unlock after a visit the guest made in person, with no browser involved. A client-side dataLayer push cannot capture those, because there is no open page to fire from. For these events, send earn_virtual_currency and purchase from your backend using the GA4 Measurement Protocol. Then pass the same client_id and user_id you captured during the guest’s last web session.
If you run server-side GTM, route these through the server container instead, which keeps client_id stitching intact. The event names stay identical to the client-side ones. As a result, your GA4 reports treat a counter redemption and an online redemption as the same event type.
The practical split: enrollment confirmed in the browser, online redemptions, and app sign-ins go client-side with the dataLayer code above. In contrast, in-store redemptions, rewards unlocked from offline visits, and card-tokenized purchase confirmations go server-side. Most Thanx restaurants need both halves, and they feed the same GA4 events without conflict.
How do you send Thanx purchase webhooks to GA4 without double counting?
Thanx purchase webhooks are the cleanest server-side source for in-store spend. However, Thanx says the same purchase arrives more than once as it moves through authorization and settlement. So dedupe on the purchase id and skip online orders your ordering tags already sent. Then post the rest to GA4 with the Measurement Protocol inside its 72-hour window.
Which rules should a Thanx webhook handler follow?
These rules come from Thanx’s webhook documentation and Google’s Measurement Protocol guide, both checked October 2026:
- Ask Thanx to switch webhooks on. Thanx enables them for integration partners on request. Your endpoint must accept HTTPS POST requests and answer within 15 seconds. Also, Thanx does not retry failed deliveries by default, so missed purchases come back through its bulk data exports.
- Verify every request. Each delivery carries an X-Thanx-Signature header, a hex HMAC-SHA256 of the payload made with a webhook secret Thanx gives you.
- Dedupe on the purchase id. By default, the first delivery comes about 10 minutes after Thanx captures the purchase. Later deliveries for the same id can then refine the amount and the product list.
- Skip what the browser already sent. Thanx fills the order field only for online orders, with a provider of OLO, Toast or Other. So if Olo already fires purchase in the browser, drop those deliveries.
- Strip personal data. The payload can include the guest’s email and name. So send only the Thanx user id as user_id and the purchase id as transaction_id.
- Send on the first delivery. Google accepts Measurement Protocol timestamps up to 72 hours old. It also says events meant to join browser data should arrive within 48 hours. Authorization and settlement are typically days apart, so waiting for settlement would miss the window.
What does a Thanx webhook to GA4 handler look like in Node.js?
The handler below checks the signature, drops repeat deliveries and browser orders, and skips purchases older than 72 hours. It then posts each remaining purchase to GA4 under the member’s saved client_id.
JavaScript, Thanx purchase webhook to GA4 (Node.js 18 or later)
// Thanx purchase webhook to GA4 Measurement Protocol (Node.js 18 or later).
// Keep both secrets on your server. Never put them in browser code.
const crypto = require('crypto');
const MEASUREMENT_ID = 'G-XXXXXXXXXX';
const API_SECRET = process.env.GA4_API_SECRET;
const THANX_WEBHOOK_SECRET = process.env.THANX_WEBHOOK_SECRET;
const EVENT_NAME = 'purchase'; // or a custom name such as in_store_purchase
const PROVIDERS_TRACKED_IN_BROWSER = ['OLO']; // add 'Toast' if those online orders already fire a browser purchase
const MAX_AGE_MS = 72 * 60 * 60 * 1000; // GA4 accepts timestamps up to 72 hours old
const seenPurchaseIds = new Set(); // use a database table in production
function isFromThanx(rawBody, signature) {
const expected = crypto.createHmac('sha256', THANX_WEBHOOK_SECRET).update(rawBody).digest('hex');
return typeof signature === 'string' && signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}
async function handleThanxPurchase(rawBody, signature, lookupClientId) {
if (!isFromThanx(rawBody, signature)) return 'rejected';
const purchase = JSON.parse(rawBody).purchase;
// Thanx resends the same purchase id, so keep only the first delivery.
if (seenPurchaseIds.has(purchase.id)) return 'duplicate';
seenPurchaseIds.add(purchase.id);
// Online orders already tracked by your ordering tags are skipped.
const provider = purchase.order && purchase.order.provider;
if (PROVIDERS_TRACKED_IN_BROWSER.includes(provider)) return 'tracked in browser';
const purchasedAt = new Date(purchase.purchased_at).getTime();
if (Date.now() - purchasedAt > MAX_AGE_MS) return 'too old for GA4';
// client_id saved from the member's last web session, keyed by Thanx user id.
const clientId = await lookupClientId(purchase.user.id);
if (!clientId) return 'no client_id';
const products = Array.isArray(purchase.products) ? purchase.products : [];
const storeName = (purchase.location && purchase.location.name) || 'In store';
const items = (products.length ? products : ['In store purchase']).map(function (name) {
return { item_name: name, affiliation: storeName };
});
const body = {
client_id: clientId,
user_id: purchase.user.id, // Thanx user id only, never email or phone
timestamp_micros: purchasedAt * 1000,
events: [{
name: EVENT_NAME,
params: {
transaction_id: purchase.id,
value: Number(purchase.amount),
currency: 'USD',
items: items
}
}]
};
const url = 'https://www.google-analytics.com/mp/collect?measurement_id=' +
MEASUREMENT_ID + '&api_secret=' + API_SECRET;
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body)
});
return response.ok ? 'sent' : 'http ' + response.status;
}
module.exports = { handleThanxPurchase };The code leaves out session_id because an in-store visit has no web session. However, Google notes that events without session_id and engagement_time_msec may not show fully in Realtime or engagement metrics.
Thanx’s amount is the purchase total it records, which can include tax. In contrast, Google defines purchase value without tax or shipping. So expect this route to read slightly high unless you can split tax out.
If you import purchase into Google Ads, consider a custom event name for store sales. Otherwise, store sales can inflate online ROAS.
Leave the consent object out to inherit the consent state GA4 already holds for that client_id. Or, when your records show the member declined, send ad_user_data and ad_personalization as DENIED. Our guide to Google consent mode covers how those signals work. Also, if you already run a server container, our server-side GTM hosting guide compares where to host it.
Thanx event code generator
Generate your Thanx dataLayer push
Pick an event, fill in the fields, and copy the exact push code. Runs entirely in your browser.
How do you validate Thanx tracking is working?
Validate in three places
First, GTM Preview: complete a test card-linked purchase and confirm thanx_signup fires once, on the transaction callback, not the button. Second, GA4 DebugView: confirm sign_up, earn_virtual_currency, and spend_virtual_currency arrive with their parameters and a populated user_id. Third, reconcile: compare GA4 counts to the Thanx dashboard after a few days. If sign_up matches new members and redemptions match the Thanx redemption report, your setup is correct.
How do you test Measurement Protocol events before they reach GA4?
Send test events to Google’s validation server at /debug/mp/collect before going live. After all, the Measurement Protocol returns a 2xx status even for a malformed event. Events sent to the validation server also never appear in reports. As a result, the validation server is the safe way to catch a bad name, parameter or timestamp.
- Point the request at the validation server. Swap /mp/collect for /debug/mp/collect. Then add validation_behavior set to ENFORCE_RECOMMENDATIONS to the body.
- Replay a real webhook. Send one stored Thanx purchase payload through your handler. When the validationMessages array comes back empty, the event passed.
- Read any messages. Each one names a fieldPath and a validationCode, such as VALUE_INVALID for a timestamp older than 72 hours.
- Check the secret by hand. The validation server does not check api_secret. So confirm it in GA4 Admin under Data streams, your web stream, Measurement Protocol API secrets.
- Go live without the flag. Send to /mp/collect without validation_behavior, then confirm the transaction_id appears in your BigQuery export the next day.
What are the most common Thanx tracking mistakes?
Firing enrollment on a button instead of the transaction callback is the headline error, because card-linked enrollment completes at payment. As a result, it inflates sign-ups and never reconciles with Thanx.
Firing enrollment on every order is the second error, caused by auto-enrollment. Without a first-purchase guard, every member order looks like a new sign-up. Gate the event so it fires once per member.
Using a card number, phone, or email as the member ID is the dangerous error. That is because it puts PII into GA4 and risks your data. Instead, use the tokenized or internal Thanx member ID.
Tracking only client-side is the incomplete error, because card-tokenized purchases and in-store redemptions happen without a browser. So capture those with the Measurement Protocol or server-side GTM.
Skipping user_id is the costly error, because without it you cannot prove Thanx members are worth more than non-members. And that is the entire reason the platform exists.
Forwarding every Thanx webhook delivery is the newest error. That is because Thanx re-sends the same purchase id through authorization and settlement. So without a dedupe step, one in-store visit becomes two or three GA4 purchases.
Passing webhook fields straight through is the privacy error, because Thanx purchase payloads can carry the guest’s email and name. Instead, send the Thanx user id and purchase id only.
Why choose Hustle Marketers for Thanx tracking?
We implement Thanx loyalty tracking the way the platform actually behaves. That means enrollment fired at payment with a first-purchase guard and rewards mapped to GA4 recommended events. It also means card-tokenized purchases captured server-side, and member identity tied to user_id so lifetime value is provable. In contrast, most setups fire a sign-up on a button and call it done. We instrument the whole card-linked model so your loyalty data reconciles with Thanx and your reporting answers real questions. We also do it without disturbing the Olo tracking you already rely on.
Hustle Marketers is a Google Partner, Meta Business Partner, and Microsoft Advertising Partner. We also have a Clutch-verified 5.0 rating and six Clutch Global Awards in Spring 2026. We hold Upwork Top Rated Plus status with a 100% Job Success Score, plus 591+ combined client reviews across platforms. In addition, our team has driven measurable results across 2,500+ brands and $780M+ in trackable client sales. Your Thanx numbers may not match GA4, or members and non-members may look identical because nothing ties them together. If so, request a free analytics audit and we will map exactly what is firing wrong and what it is costing you.
Frequently asked questions about Thanx loyalty tracking
Thanx loyalty tracking records Thanx enrollment, reward unlocks, and redemptions as GA4 events through Google Tag Manager. Because Thanx uses card-linked enrollment, events fire from transaction callbacks rather than form submits, which makes correct tracking different from a standard loyalty program.
Thanx is a restaurant guest engagement, loyalty, and CRM platform built around credit card tokenization, so purchases are tracked automatically once a guest links a card. It offers card-linked and check-in loyalty, machine-learning winback, segmentation, and access-based rewards instead of blanket discounts.
Thanx card-linked enrollment completes when a guest pays with a registered card, not when they click a button, and it can auto-enroll digital purchasers. The sign_up event must fire on the transaction callback and be gated to a guest’s first qualifying purchase or enrollment counts will be inflated.
Use sign_up for enrollment, login for sign-ins, earn_virtual_currency when a reward unlocks, and spend_virtual_currency when a reward is redeemed. These recommended events give native GA4 reporting instead of custom events.
On the transaction-complete callback for a guest’s first qualifying card-linked purchase, not on a sign-up button. Use a first-purchase guard so it fires once per member rather than on every order, since Thanx can auto-enroll digital purchasers.
How do you keep Thanx member data clean and connected?
No. GA4 prohibits personally identifiable information. Use the tokenized or internal Thanx member identifier, never the raw card, phone, or email. If you only have a phone number, hash it server-side first.
Not if you avoid the five collisions: do not fire a second purchase event, do not import a second GA4 configuration, use the same Measurement ID as Olo, keep sendEcommerceData false on loyalty tags, and stitch across domains if Olo is Olo-hosted. Done correctly, loyalty and ordering run side by side cleanly.
Some do. Card-tokenized purchases and in-store redemptions happen without a browser, so capture those with the GA4 Measurement Protocol or server-side GTM using the same client_id and user_id. Online redemptions and app sign-ins can stay client-side.
Set the GA4 user_id to a non-PII Thanx member ID and attach a loyalty_member user property. Combined with purchase events, this lets you compare members and non-members on average order value, frequency, and revenue per member across devices. For exact lifetime value, run the BigQuery query in this guide.
How do you set up, check and report on Thanx tracking?
Yes. The GTM build in this guide is vendor-agnostic and works for Thanx. Set your Measurement ID in one Constant variable, add Data Layer Variables for the loyalty fields, and point the Custom Event triggers at the thanx_ event names.
Reconcile GA4 against the Thanx dashboard. After a few days your GA4 sign_up count should match new members in Thanx and spend_virtual_currency should match the Thanx redemption report. If GA4 is higher, you are still firing on intent or repeat purchases.
Thanx integrates natively with Olo, Toast, Square, and Deliverect. With Olo, enrollment can happen inside online ordering, so Thanx loyalty tracking and ordering tracking should share one measurement model and a consistent member ID.
Yes, marking spend_virtual_currency as a key event, the GA4 name for what it used to call a conversion, is reasonable because a redemption signals an engaged returning member. Mark sign_up as a key event to track enrollment growth, and leave earn_virtual_currency standard since it can fire often.
What else do restaurants and guests ask about Thanx?
Add the Thanx dataLayer code, build the GTM variables, triggers and tags from this guide, set your Measurement ID, point triggers at the thanx_ events, fire enrollment from the transaction callback with a first-purchase guard, then validate in GA4 DebugView and reconcile with Thanx.
There is no fixed value. Each brand sets its own earn rate and reward prices in Thanx, so divide a reward’s menu value by its points cost to get the value per point. Thanx’s examples of $1 = 1 point or $1 = 10 points deliver the same value when reward prices scale to match, so compare reward prices, not point balances.
On card-linked programs, points are added automatically when you pay for a tracked purchase, with no scanning or check-in. Check-in programs can use options such as a QR code scan in store. Brands can also award welcome bonuses, birthday rewards and campaign bonus points, and you spend points on rewards in the brand’s marketplace.
Thanx’s published guides do not set one universal expiry rule for points, so it depends on the brand’s own terms. Activated rewards do expire: once a guest activates a reward, it runs on a countdown timer, which Thanx documents as 1 hour by default, and only one reward can be applied to an order at a time.









