How to send data from a GTM Server-Side container to Batch?
Google Tag Manager Server-Side (sGTM) lets you collect events on your website through a lightweight client-side snippet and forward them to your own server container before redistributing them to Batch.
This guide explains how to route those events through the Profiles API using a Batch tag template, so that browsing behavior updates your Batch profiles in real time.
How the flow works
The website sends a hit
When a visitor triggers an event, for example add_to_cart, the client-side tag library builds a small HTTP request, a "hit", containing the event name, its attributes, and the visitor identifier.
The hit is sent to your server container, hosted on a first-party subdomain you own, for example collect.yourdomain.com.
Prerequisites
Before you start, make sure you have:
A Google Tag Manager Server-Side container deployed on a first-party subdomain, for example
collect.yourdomain.com, with a GA4 Client enabled to receive incoming hits.The Batch REST API Key, Project Key, and, for anonymous visitors, the SDK API Key for your project. All three are available in your Batch dashboard, with the SDK API Key under Settings > General.
The Batch
custom_idand/orinstallation_idexposed in yourdataLayerat the time events are triggered.A Batch tag template (a
.tplfile).
A tag template example can be provided by your Batch Solutions Engineer. Review it before use, and validate what it sends before deploying it to production: you remain responsible for the configuration running in your own container.
Step 1: Expose the Batch identifier in the dataLayer
The Profile API requires an identifier to target the correct Batch profile. Both options below run client-side, in the page, not inside the sGTM container.
The server container reads these values from the incoming hit through Event Data Variables.
The custom_id comes from your own authentication system. Push it to the dataLayer when the user logs in, or when the page loads for an authenticated session.
Use the same stable identifier you rely on to recognize users across your systems.
Prefer the custom_id whenever a visitor is identified: it ensures correct profile stitching across channels.
The Batch Web SDK generates an installation_id automatically. Retrieve it client-side once the SDK has initialized, then push it to the dataLayer:
Both snippets run client-side, in the browser, and depend on the page. Push the identifier as early as possible in the page lifecycle so that it is available for every event captured by the server container.
Anonymous coverage depends on the client-side SDK. The installation_id exists only if the Batch Web SDK is initialized in the browser (see How to implement Web Push with Batch?). If for any reason the SDK is not loaded, no installation_id is generated, and anonymous events cannot be attached to a profile.
Server-side forwarding secures the collection of identified visitors through custom_id, which comes from your authentication and is independent of the SDK. It does not remove the client-side dependency for anonymous visitors.
A non-existing installation_id does not create a profile: the value must correspond to an installation the SDK actually registered.
Step 2: Create the Event Data Variables
In a server container, variables that read values from an incoming hit are of type Event Data Variable.
Repeat this step for every event attribute to forward to Batch. Create one Event Data Variable per attribute, with the Key Path matching the attribute name in the hit, for example sku or price.
Step 3: Import the Batch tag template
The Batch tag template packages the Profile API call as a configurable tag, so the identity logic and attributes are set through form fields rather than a hand-written JSON body. It also preserves attribute types.
Review the template before importing it, and confirm what it sends before publishing to production. You remain responsible for the configuration that runs in your container.
Step 4: Configure the Batch tag
Create a tag from the imported template: Tags > New > Batch (Profile API).
Configuration
REST API Key: Reference a Constant variable of type Secret that holds your REST API Key. Never expose it in client-side code.
Project Key: Your Project Key, sent in the
X-Batch-Projectheader.
Identity — Auto mode
Select Auto as the identifier type, then map both fields:
Custom User ID →
{{ED - user_id}}Installation ID →
{{ED - installation_id}}SDK API Key → A Constant variable holding your SDK API Key
In Auto mode, the tag sends the custom_id when an identified visitor is known, and falls back to the installation_id for anonymous visitors.
Prefer another mode if necessary.
Event and attributes
Event name →
{{Event Name}}Event attributes describe the action and stay attached to the event. For example:
sku→{{ED - sku}},price→{{ED - price}}Profile attributes describe the person durably. For example:
favorite_category→{{ED - favorite_category}}
Why the tag template preserves value types. In the Profile API, a number must be sent unquoted ("price": 499.99) to remain usable in numeric conditions, dates use the date() wrapper, and booleans are unquoted.
Two tags for two use cases
Depending on what you send, you can split the configuration into two tags that share the same variables:
Events tag (
Send an eventchecked): fires on your business events, for exampleadd_to_cartorpurchase. It sends the event and can also update profile attributes in the same call.Profile-only tag (
Send an eventunchecked): fires on a dedicated technical event, for exampleprofile_update. It updates profile attributes only, without writing an event to the profile. Use it when a value about the person changes, for example a language or a consent, outside of any tracked action.
To build the second tag, create another tag from the same template, uncheck Send an event, and fill in only the Profile attributes section. Both tags reuse the same Event Data Variables, so there is nothing to recreate.
Step 5: Set the trigger
Configure the tag to fire on the events to forward to Batch. This selection is where your tagging plan applies: forward the events that carry value for your orchestrations, for example purchase, add_to_cart, or view_item, not technical hits.
Create or reuse a trigger
Create a Custom Event trigger, or reuse an existing one, matching the event names to forward.
A regular expression such as add_to_cart|purchase matches several events with one trigger.
If you set up two tags as described above, give each its own trigger: the business events for the events tag, and the dedicated profile_update event for the profile-only tag. Keep the event names disjoint so that a single hit only fires one tag.
Step 6: Test and publish
Preview is not the live version. Preview runs the draft workspace; the live website uses the last published version. A change that works in Preview but not on the live site is almost always an unpublished change: publish the container after every modification.
Notes
If both
custom_idandinstallation_idare available, prefer thecustom_idto ensure correct profile stitching across channels.When identifying by
installation_id, the profile-level attributes$email_address,$email_marketing,$phone_number, and$sms_marketingare ignored if included.A
202response with{"code":"SUCCESS"}means the request was accepted. A202with{"code":"SUCCESS_WITH_PARTIAL_ERRORS"}means part of the payload was rejected and details are listed in anerrorsarray. Neither guarantees attachment on its own: if the identifier is empty, or theinstallation_iddoes not correspond to a registered installation, Batch accepts the call but attaches nothing. Always verify the profile in the dashboard.Common failures:
AUTHENTICATION_INVALID(401, wrong REST API Key)MALFORMED_PARAMETER(400, for example an invalid project key)TOO_MANY_REQUESTS(429, wait at least 5 seconds before retrying)
For the available fields, constraints, and rate limits, see the Profile API reference documentation.
Last updated

