📋 Behind the scenes: Building a PostHog A/B testing plugin for Bubble
A step-by-step guide for building a private Bubble plugin for A/B testing
Hey friends!
Today, we're diving into the world of Bubble plugin development. I recently built a private Bubble plugin for A/B testing with PostHog’s Node SDK and today’s issue features a behind-the-scenes play-by-play.
To follow along, you'll need:
A PostHog account and experiment.
A Bubble account and an app to test.
This newsletter provides an overview and code snippets to help you create your own plugin. For a deeper dive and to see how I use it within a Bubble app check out the full post.
Step 1: Create a new plugin
The first step is creating the plugin. Once you log into Bubble, go to “plugins”, select “create a plugin” and fill out the general settings
Step 2: Add a field for the API key
Next, add a private key for our Project API key in the “Shared” tab
Step 3: Create a server-side action
PostHog offers multiple SDKs.
For Bubble plugins, you can choose between client-side JavaScript or Node. For this plugin, I went with the server side.
Under "General Properties", I set the action type to "Server side" and assigned my action a name.
Step 4: Configure fields and returned values
Moving on to the "fields" and "returned values" sections. Here, I configured the input fields required for PostHog.
Anyone using the plugin can set these fields up from their workflow action.
I also set up a return field to share which variant a user was assigned.
Step 5: Activate Node modules and set up the package
5/Choose the option "This action uses node modules". Then, input your package.json`
Remember to build the package afterward.
The package.json should look like this
{
"dependencies": {
"posthog-node": "latest"
}
}
Step 6: Retrieve the API key in the action code and connect PostHog
In the action code, retrieve the API keys from Bubble's context object. Then, import PostHog using Node.js' require function. Bubble plugins don’t yet support ES6 import statements.
Step 7: Initialize PostHog and fetch feature flags
Next, initialize a new PostHog client, fetch the feature flag, and return the resulting variant.
async function(properties, context) {
const apiKey = context.keys["Project API key"];
const { PostHog } = require('posthog-node');
const client = new PostHog(apiKey, { host: '<https://app.posthog.com>' });
try {
const variant = await client.getFeatureFlag(properties.featureFlagKey, properties.distinctId);
const eventCapture = await client.capture({
distinctId: properties.distinctId,
event: properties.event,
properties: {
[`$feature/${properties.featureFlagKey}`]: variant
}
});
// Format and return the result
return {
variant: variant,
eventCapture: eventCapture
};
} catch (error) {
console.error('Error:', error);
}
}
Step 8: Set up an action that only retrieves the variant
Set up an additional action specifically to retrieve the variant. This comes in handy when you aim to determine a user's group without capturing an event. The configuration is pretty much the same as the previous action, except there's no event input field.
Step 9: Remove event capturing from the action
The action code remains the same, just omit the segments related to event capturing.
async function(properties, context) {
const apiKey = context.keys["Project API key"];
const { PostHog } = require('posthog-node');
const client = new PostHog(apiKey, { host: '<https://app.posthog.com>' });
try {
const variant = await client.getFeatureFlag(properties.featureFlagKey, properties.distinctId);
// Format and return the result
return {
variant: variant
};
} catch (error) {
console.error('Error:', error);
}
}
That wraps up the plugin details! For a closer look at how I utilize the plugin within Bubble, complete with ready-to-use code snippets, check out the write-up.
Thanks for tuning in, and if you give it a shot, I'd love to hear about it!
Cheers,
Lola