# Segment

- Tool: Bubble
- Difficulty: Beginner
- Time required: 1–2 hours
- Last updated: July 2026

## TL;DR

Bubble connects to Segment in two ways: inject the Analytics.js snippet in Bubble's HTML header for client-side event capture (write key is intentionally public), and use the API Connector with HTTP Basic Auth for server-side Tracking API calls from backend workflows. Both paths route behavioral data to all your Segment destinations — GA4, Amplitude, Mixpanel — without touching each tool individually.

## Why Segment is the hub that replaces dozens of Bubble tracking integrations

Without Segment, adding analytics to a Bubble app means installing separate integrations for Google Analytics, Amplitude, Mixpanel, Facebook Pixel, and every other tool your team uses — each requiring its own JavaScript snippet, API key, and maintenance. Segment solves this by acting as a single collection layer: Bubble sends events to Segment once, and Segment fans them out to every destination you have enabled in its dashboard. Adding a new analytics tool later means toggling it on in Segment, not modifying Bubble workflows.

The key architectural decision for Bubble builders is which capture path to use. Client-side capture via the Analytics.js snippet is easiest and handles page views and user interactions automatically. Server-side capture via Bubble's API Connector is needed for events that originate in Bubble backend workflows — like 'subscription created' or 'invoice paid' — where the user's browser is not involved. Most Bubble apps benefit from both paths, with careful tracking plan design to avoid counting the same event twice.

## Before you start

- A Segment account — free tier supports up to 1,000 MTU/month
- A Segment source created (type: Website for the Analytics.js snippet or HTTP API for server-side only)
- Your Segment write key — visible in the Source settings under API Keys
- The API Connector plugin installed in your Bubble app (free, by Bubble)
- The Toolbox plugin installed in your Bubble app (free, by Bubble) if you plan to use 'Run JavaScript' actions for analytics.identify()

## Step-by-step guide

### 1. Create a Segment source and copy the write key

In your Segment workspace, click Connections → Sources → Add Source. Choose the source type: select 'Website' if your Bubble app is a browser-based app where the Analytics.js snippet will run, or 'HTTP API' if you plan to use server-side Tracking API calls only without the snippet. Click Add Source, give it a name like 'Bubble App – Production', and confirm. Go to the source's Settings → API Keys. Copy the Write Key — it looks like a 28-character string starting with a random prefix. This write key is intentionally designed to be a send-only credential: it can create events but cannot read data. Do not confuse it with the Segment Public API Bearer token (used for workspace management), which is a separate, secret credential. The write key can safely appear in client-side HTML because anyone who obtains it can only send events to your source, not read your data.

**Expected result:** You have a Segment source with a write key copied and ready. The source appears in your Segment workspace under Connections → Sources.

### 2. Add the Analytics.js snippet to Bubble's HTML header

The Analytics.js snippet enables automatic page-view tracking and gives you access to analytics.track() and analytics.identify() functions in any JavaScript running in your Bubble app. In your Bubble editor, go to Settings (gear icon) → SEO / metatags → Script / meta tags in header. In the text area, paste the Segment Analytics.js snippet. The standard snippet loads the library asynchronously, sets your write key, and sends an initial page() call. The snippet is documented in your Segment source's Overview tab — click 'See snippet'. Replace 'YOUR_WRITE_KEY' in the snippet with your actual write key. Save and close Settings. This snippet will load on every page of your Bubble app automatically. You do not need to add it to each page individually — Bubble injects header scripts globally. Publish your app to a live URL (Bubble preview mode does not run header scripts in the same way as the deployed app). After publishing, visit your app and check Segment's Debugger tab (Sources → your source → Debugger) to confirm page() events are arriving.

```
<script>
  !function(){var i="analytics",analytics=window[i]=window[i]||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","screen","once","off","on","addSourceMiddleware","addIntegrationMiddleware","setAnonymousId","addDestinationMiddleware","register"];analytics.factory=function(e){return function(){if(window[i].initialized)return window[i][e].apply(window[i],arguments);var n=Array.prototype.slice.call(arguments);if(["track","screen","alias","group","page","identify"].indexOf(e)>-1){var c=document.querySelector("link[rel='canonical']");n.push({__t:"bpc",c:c&&c.getAttribute("href")||void 0,p:location.pathname,u:location.href,s:location.search,t:document.title,r:document.referrer})}n.unshift(e);analytics.push(n);return analytics}};for(var n=0;n<analytics.methods.length;n++){var key=analytics.methods[n];analytics[key]=analytics.factory(key)}analytics.load=function(key,n){var t=document.createElement("script");t.type="text/javascript";t.async=!0;t.src="https://cdn.segment.com/analytics.js/v1/"+key+"/analytics.min.js";var r=document.getElementsByTagName("script")[0];r.parentNode.insertBefore(t,r);analytics._loadOptions=n};analytics._writeKey="YOUR_WRITE_KEY";analytics.SNIPPET_VERSION="5.2.0";analytics.load("YOUR_WRITE_KEY");analytics.page()}}();
</script>
```

**Expected result:** After publishing your Bubble app and visiting a page, Segment's Debugger tab shows 'Page' events arriving with the page URL and title. This confirms the snippet is loading correctly.

### 3. Identify users after login with a Run JavaScript action

Tracking page views is useful, but Segment's real power comes from linking events to specific users. After a user logs into your Bubble app, call analytics.identify() to associate all subsequent events with their Bubble user ID and traits. In your Bubble editor, find the workflow that runs after a successful user login — typically the workflow triggered by the 'Log in' button. Add a new step: Action → General → Run JavaScript (requires the Toolbox plugin). In the JavaScript field, write the identify call. Use Bubble's dynamic data syntax to insert the current user's unique ID, name, and email into the JavaScript. Note that Bubble's 'Run JavaScript' action does not wait for analytics.track() or analytics.identify() to resolve before the next workflow step executes. If your next workflow step redirects the user to another page immediately, the identify call may not complete before navigation interrupts it. For critical identification calls, use the server-side Tracking API path (next step) or add a short delay workflow step before the redirect.

```
analytics.identify("[Current User's unique id]", {
  name: "[Current User's Full Name]",
  email: "[Current User's email]",
  plan: "[Current User's plan field]",
  createdAt: "[Current User's Created Date]"
});
```

**Expected result:** After a user logs in, Segment's Debugger shows an 'Identify' event with the user's ID and traits. Segment destinations like HubSpot and Klaviyo receive the user record automatically.

### 4. Add the Segment Tracking API group in Bubble's API Connector for server-side events

Client-side events require the user's browser to be active. For events generated by Bubble backend workflows — subscription renewals, automated status changes, or scheduled data operations — you need to call the Segment Tracking API directly from Bubble's server using the API Connector. In your Bubble editor, open Plugins → API Connector plugin. Click Add another API. Name it 'Segment Tracking API'. Set the base URL to 'https://api.segment.io/v1'. Under Authentication, select 'HTTP Basic Auth'. In the Username field, enter your Segment write key. Leave the Password field empty (Segment uses the write key as the username with an empty password). Click the Private checkbox next to the Username field to mark the write key as private. This is the correct approach — though the write key is technically public (send-only), using the Private checkbox keeps it out of Bubble's client-side bundle. Click Add another call. Name the first call 'Track Event'. Set Method to POST, URL path to '/track'. Under Use as, select Action. In the Body section, select JSON and add the required fields: type (text, default 'track'), event (text, leave blank — this will be dynamic), userId (text, leave blank — dynamic), and a properties object.

```
{
  "method": "POST",
  "url": "https://api.segment.io/v1/track",
  "authentication": "HTTP Basic Auth",
  "username": "<private: your_write_key>",
  "password": "",
  "body": {
    "type": "track",
    "event": "<dynamic: event name>",
    "userId": "<dynamic: bubble user unique id>",
    "properties": {
      "plan": "<dynamic: plan name>",
      "revenue": "<dynamic: amount>"
    }
  }
}
```

**Expected result:** The 'Track Event' API Connector call initializes successfully. Segment Debugger shows a 'Track' event with the test event name and userId. The call is available as a workflow action in your Bubble editor.

### 5. Build a Bubble workflow that uses the server-side track call

Now wire the server-side Track call to a meaningful Bubble event. A great first use case is tracking when a user upgrades their subscription plan — an event that happens as the result of a Bubble workflow step (after Stripe payment confirmation), not a user clicking a specific button. In your Bubble editor, find the workflow that runs after a successful Stripe payment (or after you update the user's 'plan' field in your database). Add a new step at the end of this workflow. Click Click here to add an action → Plugins → Segment Tracking API - Track Event. In the action's parameter fields, set event to a static text value like 'Subscription Upgraded', set userId to 'Current User's unique id', and set properties fields to relevant values like the new plan name and the subscription price. This track call runs from Bubble's server — even if the user closes the browser tab immediately after payment, this event will fire. Add a second API Connector call for Segment's /identify endpoint using the same authentication, with a JSON body containing userId and a traits object. Call this after the Track call to update the user's plan trait in Segment, which propagates to CRM and email tool destinations.

```
{
  "method": "POST",
  "url": "https://api.segment.io/v1/identify",
  "authentication": "HTTP Basic Auth",
  "username": "<private: your_write_key>",
  "password": "",
  "body": {
    "type": "identify",
    "userId": "<dynamic: bubble user unique id>",
    "traits": {
      "email": "<dynamic: user email>",
      "plan": "<dynamic: new plan name>",
      "plan_updated_at": "<dynamic: current date/time>"
    }
  }
}
```

**Expected result:** After a subscription upgrade workflow runs in Bubble, Segment's Debugger shows both a 'Track' event ('Subscription Upgraded') and an 'Identify' event with updated plan traits. These events flow to all enabled destinations automatically.

### 6. Enable Segment destinations and verify the tracking plan

The final step is enabling the analytics tools that receive your Segment events. In Segment, go to Connections → Destinations → Add Destination. Search for Google Analytics 4 (GA4) and click Add Destination. Select your Bubble source and configure the GA4 Measurement ID. Repeat for Amplitude, Mixpanel, or any other tool your team uses. Important: once destinations are enabled, every event Bubble sends to Segment — both client-side and server-side — is automatically forwarded. No changes to your Bubble app are needed. Review your tracking plan to avoid double-counting. The most common mistake in Bubble apps is tracking the same event from both the Analytics.js snippet (client-side button click) and the API Connector workflow action (server-side step). For example: do not fire analytics.track('Button Clicked') from a 'Run JavaScript' action AND fire a Segment Tracking API /track call for the same event from the same workflow. Choose one path per event type. Use client-side for UI interactions (button clicks, form views) and server-side for database-driven events (subscription created, record approved).

**Expected result:** Destinations are enabled and receiving events. GA4, Amplitude, and Mixpanel show incoming events without any additional code changes in Bubble. Double-counting has been eliminated by assigning each event type to exactly one capture path.

## Best practices

- Use separate Segment sources for your Bubble development and production environments. This prevents test events from polluting production analytics data and lets you validate the integration safely before pushing to production.
- Apply Bubble Privacy Rules to any data type that stores user behavioral data or PII synced from Segment. Never expose analytics event data to users who should not see it.
- Assign each event type to exactly one capture path — client-side snippet or server-side API Connector — to eliminate double-counting in destinations. Document your tracking plan in a Notion or Google Sheet so all team members know which path each event uses.
- For Bubble apps with a significant anonymous user population, set a consistent anonymousId using Local Storage (via a 'Run JavaScript' action) to maintain session continuity across page loads. Segment uses anonymousId to unify anonymous events with the user after identify() is called.
- Store Segment's write key as Private in the API Connector's HTTP Basic Auth username field. While the write key is technically a send-only credential, keeping it out of client-side bundles is a good security hygiene practice.
- Leverage Segment's Protocols (tracking plan feature) to validate event schemas before they reach destinations. Malformed events with missing required properties are flagged in Segment's Violations report rather than silently failing in downstream tools.
- Be aware of Workload Units (WU) cost in Bubble: every API Connector call to the Segment Tracking API consumes WU. For high-volume event tracking (thousands of events per day), prefer the client-side Analytics.js snippet which fires events directly from the browser without consuming Bubble WU.
- After enabling a new Segment destination, test it in staging before production. Some destinations transform events in ways that affect your existing data (for example, Mixpanel requires event names to not exceed 255 characters). Validate in Segment's Debugger first.

## Use cases

### Unified analytics for a Bubble SaaS app

Inject Segment's Analytics.js in Bubble's HTML header to capture all page views and user interactions automatically. After login, call analytics.identify() from a 'Run JavaScript' action to associate sessions with Bubble user IDs. Enable GA4, Mixpanel, and Amplitude destinations in Segment — all three tools receive data without any additional Bubble setup. Product, growth, and engineering teams each get their preferred analytics tool fed from one Segment source.

### Server-side event tracking for subscription lifecycle events

Use the Segment Tracking API from a Bubble backend workflow to send a 'Subscription Created' event when a user upgrades, or a 'Trial Expired' event when a scheduled workflow detects an expired trial. These events originate in Bubble's server, not the user's browser, so they cannot be captured by the Analytics.js snippet — only the API Connector path reaches Segment. Route these events to Segment's data warehouse destination (BigQuery or Redshift) for lifecycle analysis.

### Marketing attribution with user identification

When a new user signs up in Bubble, call analytics.identify() with their userId, email, and plan name. Segment distributes this trait data to your CRM (HubSpot or Salesforce), email tool (Klaviyo), and ad platforms (Facebook, Google). When the same user converts to paid, send a 'Subscription Activated' track event with revenue and plan properties. Segment's identity graph ties all previous anonymous events to the user's ID automatically.

## Troubleshooting

### Segment's Debugger shows no events after adding the Analytics.js snippet to Bubble's HTML header

Cause: Bubble's header script injection only runs in the published (live) app, not in the Bubble editor preview. Scripts added to Settings → SEO / metatags → Script/meta tags in header do not execute in preview mode.

Solution: Click Publish in your Bubble editor to deploy the app to your live URL. Visit the live URL (not the /version-test URL) and check Segment's Debugger. If events still don't appear, open your browser's developer console (F12) and look for JavaScript errors related to the Segment snippet — a typo in the write key or a missing closing script tag are the most common causes.

### The server-side Tracking API call returns 401 Unauthorized during API Connector initialization

Cause: Bubble's HTTP Basic Auth with an empty password requires the username field (write key) followed by a colon and no password — some API Connector configurations add a colon incorrectly or leave the authentication field as 'None'.

Solution: In the API Connector plugin, confirm the Authentication field is set to 'HTTP Basic Auth', the Username field contains your write key only (no trailing colon), and the Password field is completely empty. Segment encodes this as write_key: (Base64) in the Authorization header automatically. If you prefer, you can also manually add an Authorization header with value 'Basic BASE64(write_key:)' marked as Private instead of using the built-in auth field.

### The API Connector shows 'There was an issue setting up your call' when initializing the Tracking API /track call

Cause: The Initialize call requires Bubble to make a real successful HTTP request to Segment and receive a parseable JSON response. If the request body is missing required fields (type, event, userId or anonymousId), Segment returns an error that Bubble cannot parse as a valid data structure.

Solution: During initialization, hardcode test values for all required body fields: type='track', event='Test Event', userId='test-user-123'. Segment returns {"success": true} on a valid request. After initialization succeeds, switch to dynamic data references for the real workflow. If anonymousId is needed for logged-out users, generate a UUID using Bubble's built-in 'Generate a random string' capability.

### Events are counted twice in GA4 or Amplitude — once from the snippet and once from the API Connector

Cause: Both the client-side Analytics.js snippet and the server-side API Connector are sending the same event. For example, a button click workflow runs analytics.track() in a 'Run JavaScript' action AND calls the Segment Tracking API as a subsequent step.

Solution: Audit each event in your tracking plan and assign it to exactly one capture path. UI interactions (button clicks, form views, page navigation) should use the client-side snippet exclusively. Server-generated events (subscription created, invoice paid, scheduled job completed) should use the API Connector exclusively. Remove duplicate track calls from workflows where both are firing.

### Segment Tracking API calls from backend workflows fail — 'Workflow API is not enabled' error

Cause: You are attempting to use an API Workflow (backend workflow) in Bubble to make the Tracking API call, but API Workflows are only available on paid Bubble plans.

Solution: Server-side Segment tracking from scheduled or webhook-triggered backend workflows requires a paid Bubble plan (Starter or above). If you are on the free plan, use the client-side Analytics.js snippet and 'Run JavaScript' actions in user-triggered workflows instead of backend workflows.

## Frequently asked questions

### Is the Segment write key safe to include in Bubble's HTML header?

Yes. Segment's write key is intentionally designed to be a client-side, public credential. It is send-only — anyone who obtains it can send events to your Segment source but cannot read your data, modify your workspace, or access any historical events. This is analogous to GA4's Measurement ID or a Stripe publishable key. Do not confuse it with the Segment Public API Bearer token, which is a secret management credential that should always be stored Private.

### Do I need a paid Bubble plan to use Segment?

No — the client-side Analytics.js snippet and user-triggered workflow actions work on the free Bubble plan. A paid Bubble plan is only required if you want to use Backend Workflows (API Workflows) for server-side Segment tracking triggered by scheduled jobs or incoming webhooks.

### Can Segment send data into Bubble, or does data only flow from Bubble to Segment?

The standard Segment integration with Bubble is one-directional: Bubble sends events to Segment, and Segment routes them to destinations. Segment does not push data back to Bubble natively. To get Segment data into Bubble, you would need to use Segment Destinations that write to a database (like BigQuery or Postgres), then query that database from Bubble's API Connector.

### How do I track anonymous users before they log in?

The Analytics.js snippet automatically generates an anonymousId for each new visitor and stores it in a cookie. Events tracked before login are associated with this anonymousId. When the user logs in and you call analytics.identify(), Segment automatically merges the anonymous event history with the new userId using its identity resolution feature. For server-side tracking of anonymous users, generate a UUID in Bubble and pass it as the anonymousId field in the Tracking API body.

### Can I use Segment with Bubble's multi-tenant apps where different customers have different Segment sources?

It is possible but complex. The Analytics.js snippet in the HTML header uses a single write key, which routes all events to one source. For true multi-tenancy with separate Segment sources per customer, you would need to load the Segment snippet dynamically via a 'Run JavaScript' action after determining the tenant context, using a different write key per tenant. This is an advanced configuration — RapidDev's team has built hundreds of Bubble apps including multi-tenant analytics setups. Free scoping call at rapidevelopers.com/contact.

### What happens to Segment events if I switch from one Segment pricing plan to another?

Events already sent to Segment are stored in your source's event history according to your plan's retention period. Upgrading or downgrading does not delete historical events (within the retention window). If you exceed the free plan's 1,000 MTU limit, Segment stops processing new events until the next billing period or you upgrade. Monitor your MTU usage in Segment's workspace settings.

---

Source: https://www.rapidevelopers.com/bubble-integrations/segment
© RapidDev — https://www.rapidevelopers.com/bubble-integrations/segment
