How to set up PostHog for a Bubble single-page application, with proper pageview tracking
Bubble is a no-code platform for building web applications. PostHog is a product analytics platform that can record how users interact with your application.
PostHog has an official guide to installing PostHog on Bubble. This gets you set up with the basics, but by default it won't record pages correctly if you're using client-side navigation (the 'Go to page...' Bubble action).
This article explains how to set up PostHog analytics on a Bubble single-page application. This will enable you to track page movements.
Step 1: Adding PostHog to Your Bubble App
Start by following the official guide to installing PostHog on Bubble. In short, this involves pasting the web snippet into the Site settings > SEO / metatags > Script/meta tags in header
section.
Step 2: Enabling single-page application pageview tracking
Then, add the following script just after your call to posthog.init
:
// Custom script to capture Bubble SPA navigation, by Adam Jones (domdomegg)
const originalPushState = history.pushState;
history.pushState = function () {
const result = originalPushState.apply(this, arguments);
const event = new Event('pushState');
window.dispatchEvent(event);
return result;
};
window.addEventListener('pushState', () => {
posthog.capture('$pageview');
});
What should the full thing look like?
Together, the Site settings > SEO / metatags > Script/meta tags in header
value should be something like this:
<script>
!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="capture identify alias people.set people.set_once set_config register register_once unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset isFeatureEnabled onFeatureFlags getFeatureFlag getFeatureFlagPayload reloadFeatureFlags group updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures getActiveMatchingSurveys getSurveys getNextSurveyStep onSessionId".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
posthog.init('phc_YOUR_API_KEY',{api_host:'https://eu.i.posthog.com'})
// Custom script to capture Bubble SPA navigation, by Adam Jones (domdomegg)
const originalPushState = history.pushState;
history.pushState = function () {
const result = originalPushState.apply(this, arguments);
const event = new Event('pushState');
window.dispatchEvent(event);
return result;
};
window.addEventListener('pushState', () => {
posthog.capture('$pageview');
});
</script>
(this is just so it's clear where to put the scripts - you should copy the PostHog script from the official guide so it uses your key, and in case they update it!)
Why You Need the Custom Script
Bubble applications are single-page applications (SPAs), which means they don't perform full page reloads when users navigate between different pages or views. Instead, they dynamically update the content on the page.
This creates a challenge for analytics tools like PostHog, which typically track page views when a page loads. In a SPA, the page only loads once at the beginning, so you won't get page view events when users navigate within your app.
How the Custom Script Works
The custom script we added solves this problem by:
-
Intercepting navigation events: The script creates a modified version of the browser's
history.pushState
method, which is what Bubble uses to change the URL when users navigate within the app. -
Creating a custom event: When
history.pushState
is called, the script triggers a custompushState
event. -
Capturing page views: The script sets up an event listener for this custom event, and when it occurs, it tells PostHog to capture a
$pageview
event.
In simpler terms, the script watches for changes to the URL in your Bubble app and tells PostHog "Hey, the user just viewed a new page!" whenever that happens.
Step 3: Testing Your Implementation
To verify that your PostHog implementation is working correctly:
- Make the changes above, and publish your Bubble app
- In your Bubble app, navigate between different pages
- In PostHog, check the 'Activity' panel to see if pageview events are being recorded
Conclusion
Congrats! By implementing PostHog analytics in your Bubble application, you'll be able to see how users interact with your app. The custom script ensures that you capture page navigation events correctly, giving you accurate data about user journeys through your application.