Install on Bubble
Settings SEO/metatags Header field for the install. Conversion fires from an HTML element on the post-signup success page using Bubble's dynamic email expression.
Bubble treats <script>, <meta>, and <link> as the only valid head tags in its Settings > SEO/metatags > "Script/meta tags in Header" field. Anything else (notably <noscript>) gets repositioned to <body> by the browser automatically. That's fine for our install — the <noscript> fallback fires its 1x1 pixel correctly from <body>. The conversion-fire step uses Bubble's HTML element on the post-signup success page, with Bubble's dynamic expressions for email and plan price.
Install the head script
In the Bubble editor: Settings > SEO/metatags > Script/meta tags in Header.
Paste:
<script>
(function(){
var s=document.createElement('script');
s.src='https://js.rekomi.com/v1/rekomi.js';
s.async=true;
s.dataset.programId='YOUR_PROGRAM_ID';
document.head.appendChild(s);
})();
</script>Save and Deploy to live. Your program ID is in Rekomi at Settings > Tracking.
Build the signup-to-success workflow
Bubble's typical SaaS signup flow:
- User submits signup form → Bubble creates the User record
- Bubble's Stripe.js plugin (or your custom Stripe API workflow) creates a Stripe Customer
- Stripe Element collects payment method, creates a subscription
- Bubble redirects to a success page (must be logged-in-only)
- Convert event fires on the success page
The success page is where the convert snippet runs.
Fire the conversion on the success page
On the post-signup success page in the Bubble editor:
- Add an HTML element to the page (Bubble's HTML element renders raw HTML inside a div).
- Paste:
<script>
window.Rekomi && window.Rekomi.convert({
external_event_id: 'BUBBLE_USER_ID',
amount_cents: 9900,
currency: 'USD',
customer_email: 'CURRENT_USER_EMAIL',
});
</script>- Replace
BUBBLE_USER_IDwith Bubble's dynamic expressionCurrent User's unique id. - Replace
CURRENT_USER_EMAILwithCurrent User's email. - Replace
9900with the plan price in cents. If you have multiple plans, use a Bubble conditional that selects the price based onCurrent User's plan(or whichever field stores the active subscription).
The convert event fires when the success page loads. external_event_id is the Bubble user id so retries don't double-credit.
Alternative: Bubble's Stripe.js plugin webhooks
If you'd rather fire conversions server-side (more reliable, survives ad-blockers and analytics blockers), have your Stripe webhook backend POST to Rekomi's /api/tracking/s2s endpoint with HMAC. The browser-pixel path above is simpler to set up; webhook-driven is more durable for production.
See the S2S tracking API reference for the HMAC pattern, and the Install on Stripe doc for Stripe-side webhook configuration.
Quirks worth knowing
Valid head tags only. Bubble's "Script/meta tags in Header" field accepts <script>, <meta>, and <link> only. Other elements get auto-relocated to <body> by the browser. Don't try to install via comments or block-level elements — they get stripped.
<noscript> ends up in <body>. That's by browser design (not a Bubble bug). The 1x1 pixel fallback inside <noscript> still fires correctly from <body> for JS-disabled visitors.
HTML element vs Embed. Bubble has two ways to inject HTML on a page: the HTML element (renders inside a <div>) and the page Settings > "Page HTML Header" field (renders in <head>). Use the HTML element for the convert snippet because it runs after Bubble has populated Current User's email. Page HTML Header is for static globals only.
Live vs Development mode. Bubble has separate Development and Live deployment modes. The head script in Settings > SEO/metatags applies to both, but you have to Deploy to push to Live after editing.
Bubble's Stripe.js plugin handles subscription creation. The success page only fires after Bubble has confirmed the subscription is active. If you fire convert too early (e.g., before subscription creation completes), you'd attribute a click that didn't result in a paid sale. Trust Bubble's workflow ordering.
Refunds
If you use Bubble's Stripe.js plugin, refunds fire charge.refunded to your Stripe webhook listener. Forward to Rekomi's /api/tracking/refund from your Stripe webhook handler. Use the same external_event_id (the Bubble user id) that was used for the original conversion.
Troubleshooting
Convert fires with placeholder data instead of dynamic values. You forgot to replace BUBBLE_USER_ID and CURRENT_USER_EMAIL with Bubble's dynamic expressions in the editor. The HTML element doesn't interpolate — Bubble does that at workflow time. Make sure the dynamic expression chips are pasted into the HTML element's content.
HTML element renders inside a visible <div> on the success page. It does. Wrap the HTML element's content in <script> tags only (no visible content) so the page doesn't show the snippet text to users.
Convert fires before subscription is active. Your workflow is firing the success page navigation before the Stripe subscription creation completes. Add a Bubble condition that waits for the Stripe response before redirecting.
Click cookie missing on success page. The visitor reached signup via a path that bypassed your Rekomi-bearing pages. Confirm the head script is in Settings > SEO/metatags (global), and that affiliates send traffic to a public Bubble page where the head install loads.
Related
- JavaScript pixel reference
- S2S tracking API reference
- Install on Stripe — for Stripe webhook configuration
Install on Wix
Dashboard Custom Code (not the Editor) with Head placement. Paid plan required. Skip Velo HTML iframes, they run in a sandbox that cannot read window.Rekomi.
Install on Carrd
Hidden Embed element with Location set to Head, or Pro Plus Site Settings Code field. Carrd's single-page nature means the cookie persists naturally.