Skip to main content

Prerequisites

  • Google Tag Manager installed on your website
  • Your Formbricks Workspace ID (Settings → Workspace → Connect Your App)
  • Your App URL: https://app.formbricks.com (or your self-hosted URL)
Use PUBLIC_URL for multi-domain setups, WEBAPP_URL for single-domain setups.

Basic Setup

1

Create a Custom HTML tag in GTM

  1. Create a new tag with preferred name e.g. “Formbricks Intercept Surveys”
  2. Tag Type: Custom HTML
  3. Paste the code from Step 2. Make sure to replace <your-workspace-id> and if you self-host, replace <your-app-url>
2

Add initialization script

Add GTM Custom HTML tag
3

Set trigger

  1. Trigger: All Pages - Page View (default) or use case specific event
  2. Save and publish Add a trigger
4

Test

  1. Use GTM Preview mode
  2. Verify the tag fires
  3. Add ?formbricksDebug=true to the URL to see test logs in browser console (see Debugging Mode for more details)

Formbricks Events in the Data Layer

The SDK pushes its own lifecycle events to window.dataLayer, so you can trigger GTM tags off what Formbricks actually did rather than guessing at timing. formbricks_survey_shown reports what the respondent saw, so every appearance is paired with a formbricks_survey_closed. The Displays number in your Formbricks dashboard counts what reached the server instead, so it can be lower if the network dropped — worth knowing before you reconcile a GTM-side count against the dashboard. The push happens through the standard window.dataLayer = window.dataLayer || [] idiom, so it survives load order: events emitted before GTM loads are still in the array when GTM drains it.
1

Create a Custom Event trigger

  1. Triggers → New → Trigger Type: Custom Event
  2. Event name: the event you want, e.g. formbricks_setup_successful
  3. Save and publish
2

Read the payload with a Data Layer Variable

The payload is nested under a formbricks key rather than spread flat, so it cannot collide with your own data layer keys — action in particular is one of the most common keys in an ecommerce data layer.
  1. Variables → New User-defined Variable
  2. Variable Type: Data Layer Variable
  3. Data Layer Variable Name: formbricks.surveyId (or formbricks.responseId, formbricks.finished, formbricks.action, formbricks.workspaceId)
  4. Save and publish
Every push carries the full set of keys, with null for the ones that event does not set. That is deliberate: GTM merges pushes recursively, so a partial push would let survey A’s responseId still resolve under survey B’s formbricks_survey_shown. Check for null rather than assuming a key is absent — and note that responseId is optional on formbricks_response_submitted itself, so it reads null there too whenever the stored id is not available. A tag that needs the id has to tolerate that.
For the JavaScript equivalent of these events, see Lifecycle Events.

User Identification

Identify users to enable targeting and attributes. Learn more about user identification.
User identification is part of the Formbricks Enterprise Edition.
1

Create GTM variables

  1. Go to Variables on GTM dashboard
  2. Create new User-defined variable
  3. Name it (e.g., “User ID”)
  4. Variable Type: Data Layer Variable
  5. Data Layer Variable: “userId”
  6. Save and publish
  7. Repeat for attributes you want to track e.g. “userEmail” and “userPlan” (optional) Create a variable
2

Create identification tag

New Custom HTML tag named “Formbricks - User”:
3

Set triggers and push data

Attach two Custom Event triggers to the “Formbricks - User” tag, so it runs whichever of the two things happens last:
  1. user-login — your own event, for a user who signs in after Formbricks is already running.
  2. formbricks_setup_successful — the SDK’s readiness event, for a user who was already signed in when the page loaded. GTM’s data layer is a merged model, so {{User ID}} still resolves to what your earlier user-login push set. User Login Trigger
  3. In your code, push data with the same event name:
Both guards in the tag are cheap and both matter: window.formbricks may not exist yet on the user-login path, and {{User ID}} may not be set yet on the formbricks_setup_successful path. Whichever fires second does the work.
Earlier versions of this guide polled for window.formbricks every 100 ms. Use the formbricks_setup_successful trigger instead: it is exactly the signal the polling was approximating, it fires once, and it cannot time out on a slow connection.

Track Custom Events

1

Create code action in Formbricks

Add code action via Formbricks UIAdd a code action to open source in app survey
2

Create GTM variable for Event Name

  1. Go to Variables on GTM dashboard
  2. Create new User-defined variable
  3. Name it “Event Name”
  4. Variable Type: Data Layer Variable
  5. Data Layer Variable: “eventName”
  6. Save and publish Create Event Variable
3

Create event tracking tag

New Custom HTML tag:
4

Create custom trigger

  1. Create a custom event trigger in GTM
  2. Trigger Type: Custom Event
  3. Event name: eventName or name that matches with your event in code.
  4. Attach this trigger to your event tracking tag
  5. Save and publish Track Event Trigger
5

Fire events from your site

Set Embedded Data

setEmbeddedData() attaches context to the surveys displayed after it, without tying it to a trigger. A value stays in the bag for the rest of the page load, so it reaches every survey shown from then on until you remove the key. It is the GTM-native way to get a page type, a plan or a campaign onto a response. Read the full reference for the semantics; this is the tag manager wiring.
1

Declare the fields on the survey

In the Formbricks editor, add a Hidden Field for every key you intend to push. A key no survey declares is dropped and logged, never stored.
2

Create Data Layer Variables for your values

One per key, e.g. a Data Layer Variable reading pageType, and another reading plan.
3

Create the tag

New Custom HTML tag named “Formbricks - Embedded Data”:
4

Trigger it

Attach two triggers: All Pages, and a Custom Event trigger on formbricks_setup_successful.Both are needed. The SDK script loads asynchronously, so on an ordinary page load the All Pages trigger can run before window.formbricks exists — the tag returns having set nothing. The readiness trigger covers that, and All Pages covers the pushes that happen once the SDK is already running. The tag is safe to fire more than once: each call merges into the bag rather than replacing it.
Passing every key unconditionally is the intended idiom here. A variable that resolves to undefined on the current page is skipped, so it cannot clear the value another page set. Push null when you actually want to remove a key.
On a single-page app, one page load spans many routes and nothing re-pushes for you, so a pageType set on the pricing page is still in the bag when a survey opens somewhere else. Fire the tag on your app’s own route-change event as well, and push null for keys the new route has no value for. See Clearing for removing one key or the whole bag.

Troubleshooting

Surveys not showing?
  • Use GTM Preview mode to check tag firing
  • Add ?formbricksDebug=true to your URL
  • Check browser console for errors
  • Wait 1 minute for the Server Cache to refresh
User ID not working?
  • Verify Data Layer push syntax
  • Check GTM variables are reading correct values
  • Make sure the tag is also triggered by formbricks_setup_successful, so it runs whichever of “user logged in” and “SDK ready” happens last
Events not tracking?
  • Confirm window.formbricks exists before calling track
  • Match event names exactly with Formbricks action names
  • Check timing - Formbricks must be initialized first. Trigger on formbricks_setup_successful rather than polling for the global
Embedded Data not on the response?
  • Confirm the survey declares a Hidden Field with exactly that name
  • Add ?formbricksDebug=true to the URL: every setEmbeddedData call prints the keys it set and what the bag now holds
  • Remember the bag is snapshotted when the survey is displayed, so a value pushed after that lands on the next response

Need Help?