This means that you are not sending the same client_id or session_id that the client had on the web events.
You need to check that you are sending these parameters correctly, you may not have formatted the values of the cookies from where you get this data correctly.
This is similar to the _ga cookie value you use for client_id. When server side tracking GA4 uses FPID cookie for client_id. So you need to use the value from there.
If I remember correctly - the hash without numbers at the end is used, but you can check how it is sent in web tracking in the outgoing GA request from the server container.
Session id is stored in the cookie ga_{your measurement id}
I’m trying to understand how to retrieve the FPID cookie (both hashed and number part) to use as the client_id when sending the purchase event to GA4 via webhook. Could you share how you’re pulling it?
I’m working on an implementation based on this approach:
Here’s what I have so far:
On the checkout_started event, I’m saving the cart_token using a Shopify custom pixel. The pixel fires a custom event and sends a payload with parameters/cookies to sGTM. That payload gives me:
session_id (parsed from _ga_XXXXXX) – e.g. 1750443603
client_id (parsed from _ga) – e.g. 1998547898.1750367291
…and a few others.
I want to store these values in Stape Store, so I can use them later with the purchase webhook and match them via the cart_token.
Where I’m stuck:
How can I get the FPID cookie for the matching cart_token? Or should i do another Store write to match on session id?
And how do I parse it in sGTM if there’s no built-in variable type to extract it?
Apologies if any of this is off - appreciate any guidance or ideas you might have to help me move forward.
I believe there are multiple ways of doing it, but this is in short, how i do it:
Push an event to the datalayer with cart_token and fire that on begin checkout and then store that (begin_checkout event with the cart token) in Stape Store with all the event data from begin checkout, where we have client id , session id and everything else that comes with a ga4 client hit.
Then I have created my own custom client, which claims the webhook and fetches the data from Stape Store via Stapes API and then merges that togehter with the data from the webhook which has all productdata and userdata from the purchase and thus “simulating a client hit”. This way it all gets mapped automatically and no need for a lot of lookup variables and manual mapping.
Amazing! Thank you so much @jeppe_Nielsen ! I’ll be looking at this closely today. To confirm - the cart_token is included in begin_checkout in web GTM (parsed from URL - /checkouts/cn/XXXXXXXXX ?) as a parameter and when it hits the server it’s there along with all other parameters to use for stiching? Thank you!!!
FPID is https only cookies, so you cant get it via JS.
Therefore, the simplest option here is to set the FPID copy without the HTTP only flag so that it is accessible to JS. This way, you can retrieve it on the web, format it, and send it to sGTM along with the event.
You can set the FPID copy using the CookieMonster tag for example. Data Client also has a native option to set the FPID copy cookie without http only.
Thank you for the tip about the Cookie Monster tag - I used it and I was able to set a copy of FPID and pull it to sGTM in the format ready for client_id. (For some reason I couldn’t accomplish the same with the “Expose FPID Cookie” option enabled for the Data Client - couldn’t get it to set the FPIDP cookie.. ) For now I changed to JS Managed cookies but will turn the server managed back on.
The problem that I see is that even if I get correct IDs from cookies it’s not always possible to get the cart_token from the previous events (as begin_checkout doesn’t always fire - ex when people use the shop app option) - some purchase webhooks are firing without any events with matching cart_token preceding them. That happens with ~15-20% of transactions. Is it normal or there are ways to handle such cases?
I also notice that sometimes webhook purchase event fires before or at the same time with the native GA4 purchase event. When that happens the “duplicate transaction checker” fails and both the webhook and native purchase event are sent to GA4 resulting in duplicates. I saw there was a request delay tag power up - is it to address cases like that?
I dont know about your prolem with Shop app option - but yes, you need to delay the webhook because of race condition with ga4 native hit, otherwise its not gonna work properly. Stape has the request delay feature, but there are multiple ways you can delay the webhook
Thanks @jeppe_Nielsen! I’m looking at different options for that - appreciate if you could point me in the right direction here! Is it something you dod via a custom client you mentioned or custom tag?