One of the biggest blockers for Google Tag Manager’s server-side tagging to slip out of beta is Google Ads. Until server-side tagging supports a solution for both conversions and remarketing capabilities to be reproduced server-side, it’s unlikely that Server containers will lose their beta label.

While I can’t say what will happen to the beta label now, the fact is that Google Tag Manager has now released support for Conversion tracking using server-side tagging.

The whole thing is quite … interesting, as it involves not just server-to-vendor calls, but also browser-to-server-to-browser-to-vendor requests. Why? Maybe you guessed it: third-party cookies.

In this article, I’ll show you how to set things up (surprisingly simple), and I’ll also try to shed some light on how the whole setup actually works (surprisingly difficult).

Here is the official documentation on Google Ads and Server-side Tagging: Google Ads conversions (Google).


The Simmer Newsletter

Subscribe to the Simmer newsletter to get the latest news and content from Simo Ahava into your email inbox!

The components you’ll need

In the web container, you need to reconfigure the Google Analytics 4 Config tag to send the data to the Server container using the new Send to server container option. This replaces the transport_url setting you’ll have used until now.

Note! Server-side tagging with Google Ads only works with Google Analytics 4. It will not work with Universal Analytics tags.

The point here is that you’ll use your GA4 web tag(s) to send the conversion events to the Server container, where they will then be mapped accordingly.

In the Server container, you’ll need these two tags:

  • A Conversion Linker tag for sending the landing page beacons to Google as well as for writing the first-party cookies with the ad click information.
  • Google Ads Conversion Tracking tag(s) for tracking the conversions themselves.

Both of these are new, built-in tag templates in all Server containers.

Let’s start from the top.

Web: Update the GA4 Config tag

For the Google Ads setup to work, you’ll need to update the Google Analytics: GA4 Configuration tag to use the new Send to server container setting, and you’ll need to remove the transport_url field.

You need to populate the Send to server container setting with the exact same value you populated transport_url with: the origin of the Server container, i.e. the URL up to the path selector. See the image above for an example.

How it works

When you set the new Send to server container setting, it does two things.

  1. It sets the transport_url to point to the Server container.
  2. It sets the first_party_collection field to true.

The second is quite important in this scenario. The purpose of the field is to tell GA4 (in the web) that the target machine is not a computer owned by Google Analytics. This means that it enables the protocol to share potentially sensitive data, as the Server container is something owned by the company running the website (hopefully) and not Google Analytics.

When first_party_collection is enabled, GA4 will use a new protocol that allows the Server container to communicate back to the browser.

This protocol is essentially a response message, which is then parsed by the GA4 web tags, and they will react accordingly (e.g. send the request to the DoubleClick domain as in the example above).

We’ll return to this topic, but suffice to say this is done because Conversion Tracking still makes use of third-party cookies.

Server: Create a Conversion Linker tag

In the Server container, create a new Conversion Linker tag. You’ll find it in the list of built-in tag templates.

There’s a new built-in trigger called All Pages in the Server container. Add that to the tag, as you’ll want the Conversion Linker to activate on all pages.

The All Pages trigger fires whenever there’s an event named page_view generated by a Server container Client.

How it works

The Conversion Linker tag does two things.

  1. It sends a landing page beacon to the Google Ads server.
  2. If the page URL has the gclid parameter, or if there are Google Ads’ first-party cookies in the request, the tag will set the new FPGCLAW cookie in the response, writing the click ID to storage.
The landing page beacon sent to Google Ads servers The landing page beacon sent to Google Ads servers

The landing page beacon is very non-descript. It’s just a ping to Google Ads with the current URL. Naturally, the URL might contain the gclid parameter, so I’m guessing this is used to validate clicks on ads.

The FPGCLAW cookie written with a 3-month expiration The FPGCLAW cookie written with a 3-month expiration

The FPGCLAW cookie seems to just replicate the pre-existing Google Ads cookies in that it writes the Google Ads Click ID into a first-party cookie. Naturally, as it’s done in a Set-Cookie server response, it’s better warded against tracking protections.

Server: Create a Google Ads Conversion Tracking tag

Next, you can go ahead and create a Google Ads Conversion Tracking tag in the server. You configure it exactly as you would configure the same tag in a web container.

Set it to fire on whatever trigger you want to use for this particular conversion. In the example above, I’m using an add_to_cart event generated by the GA4 Client.

How it works

This is where things get interesting.

If there’s a first-party click ID available, such as the one stored in FPGCLAW by the Conversion Linker tag, the Server container sends the conversion event directly to Google Ads servers.

This is a “normal” Google Ads Conversion request. It contains the conversion ID, the conversion label, and the Click ID in the gclaw parameter, among other things.

But when you then look at the response back from the Google server, you’ll see it’s a 302 redirect to the DoubleClick domain.

Why? Because the Google Ads Conversion tag needs to communicate with the DoubleClick domain to stitch the conversion information with the user’s identity, and this requires DoubleClick to read its cookies in third-party context.

However, since the Server container can’t work with third-party cookies, things get complicated.

What happens is that the HTTP response back from the Server (i.e. for the add_to_cart event) contains a message that instructs the GA4 library in the browser to compose the DoubleClick request instead.

And sure enough, if you look at the network requests (in a browser that supports third-party cookies), you’ll see the browser requests to Google servers:

In case the browser doesn’t have first-party click ID information stored, the Server container doesn’t send a direct request to Google servers. Instead, it just instructs the browser to send the requests, so that the third-party cookies can be picked up.

Please don’t ask me what happens if the browser doesn’t support third-party cookies. My guess is that if the Click ID is present, your conversion measurement will work just fine. However, there might be limitations on what type of audiences you can use or build for conversion tracking, because the click and the conversion can’t be attributed to a generic Google user without third-party cookies.

Similarly, if the first-party Click ID is not available, I’m guessing Google uses third-party cookies to see if the user has interacted with the ad nevertheless. So you’ll lose that fallback if third-party cookies are not supported.

What about Consent Mode? What happens if ad_storage is denied? Or what if it’s subsequently granted?

First, the Conversion Linker tag sends the landing beacon ping to Google servers, but it doesn’t write the FPGCLAW cookie in the HTTP response.

The landing page beacon includes parameters which state that Consent Mode is active. These instruct Google to ignore any identifiers in the request and only collect anonymous data for conversion modeling.

The Conversion Tracking tag sends the server-to-server request normally, whether a first-party click identifier is available or not:

If the page URL has the gclid parameter, then that is sent to Google Ads (as in this scenario no Ads cookies are needed).

If, however, consent changes to granted, the GA4 web tag reacts.

The page_view hit is immediately resent to the Server container. This time it doesn’t have the consent restrictions in place, so both GA4 tags and Google Ads tags will be able to benefit from the regular, cookies-enabled ping.

This means that the Conversion Linker (assuming it fired on All Pages) will fire again and this time rewrite the FPGCLAW cookie.

In addition to this, any other event you have marked as a conversion in the Google Analytics 4 user interface will also get sent again.

In other words, if you want your add_to_cart Google Ads conversion event to be sent with cookies and full capabilities as soon as consent is granted, you need to go into the Google Analytics 4 UI and mark the add_to_cart event as a conversion.

The GA4 UI will instruct the gtag.js library to account for the add_to_cart conversion event when sending the hits again after consent is granted. You need to do this for all events that you want the library to send again once consent is granted!

Note! Even though the hits are sent again, the Server container will prevent tags from triggering again unless they support ad_storage.

By the way, this applies to analytics_storage as well (of course nothing is sent to Ads in this case). When analytics_storage is set to 'granted', GA4 collects the page_view and all previously sent, cookieless conversion events again automatically.


Finally, there’s a new Custom Template API: sendPixelFromBrowser. This API works together with a GA4 web tag. If the API is invoked and the request originated from a GA4 web tag, the API sends the pixel request back to the browser using the same protocol as the Google Ads tags above.

The GA4 web tag then picks up this instruction and sends the request via the browser.

This means that other vendors that require third-party cookies to run can utilize this API to engineer their templates to use the browser rather than direct server-to-server hits.

Note! This only works with a GA4 web tag. If the request originates from some other dispatch source, the API will not work as intended.


As you can see, setting up Google Ads tracking is quite simple. But understanding the flow is another thing indeed.

I’m actually somewhat disappointed at how the setup works. I’m not saying I don’t think it’s a good piece of software – it is! I just dislike the fact that it relies on third-party cookies.

Forcing the browser to do all the legwork means that some of the most important security benefits of server-side tagging (reliance on first-party connections only, stricter Content-Security Policies) need to be abandoned in favor of getting more data.

I’m wondering why Google isn’t pushing more aggressively for a first-party-only approach such as Enhanced Conversions. I’m not really a big fan of this, either, but at least the website and server-side tagging setup would retain control, rather than having it relinquished to third-party requests that originate in the browser.

Maybe Google is waiting for a resolution on the Privacy Sandbox initiative before making drastic changes to their data collection methods. Who knows?

Well, anyway. I think this setup for Google Ads is pretty neat simply because it’s very frictionless (the above issues with security notwithstanding). Setting it up is just as “easy” as setting up the respective components in the web container.

I think the protocol for instructing the browser to do something is a genius piece of work, but I do worry about the increased reliance on GA4 and gtag.js for server-side tagging to work its magic. It’s not a trend I’d like to see more of in the future, but I have a hunch that Google will push for a tighter and tighter integration as time goes by.

Please let me know in the comments if you have any thoughts to share on this topic!