Skip to main content
Implementation patterns for the most common B2C subscription architectures. Each includes realistic timelines and step-by-step code. How to use this guide: Find the pattern that matches your architecture below and follow along. You only need to read one section – skip the rest.

Stripe Hosted Checkout

Timeline: 30-60 minutes Common for: Subscription companies using Stripe’s hosted checkout page

The challenge

Click IDs (gclid, fbclid) get lost when customers redirect to Stripe’s hosted checkout. When they complete purchase and return to your site, you can’t connect the conversion to the original campaign.

How Fidero solves this

Browser State Capture preserves click IDs before redirect. When the purchase event arrives via webhook, our server enriches it with persisted attribution automatically.

Implementation

1

Install pixel on marketing site

<script>
  fidero.load()
  fidero.init("YOUR_PROJECT_ID")
  fidero.page() // Captures gclid, fbclid, UTMs immediately
</script>
Pixel automatically captures and persists gclid, fbclid, UTMs and referrer data.
2

Track checkout_started before redirect

// Before redirecting to Stripe
fidero.track({
  event: "checkout_started",
  properties: {
    value: 29.99,
    currency: "GBP",
    items: [{
      item_id: "premium_plan",
      item_name: "Premium Monthly",
      price: 29.99,
      quantity: 1,
    }],
  },
})

// Then redirect to Stripe
window.location.href = stripeCheckoutUrl
3

Track subscription_started from webhook

// Server-side webhook handler (runs when Stripe confirms payment)
await fetch("https://api.fidero.com/v1/track", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${FIDERO_API_KEY}`,
  },
  body: JSON.stringify({
    projectId: "YOUR_PROJECT_ID",
    userId: customer.id, // CRITICAL: Must match user who started checkout
    event: "subscription_started",
    properties: {
      transaction_id: session.id, // CRITICAL: Enables 98% deduplication
      value: session.amount_total / 100,
      currency: session.currency,
      subscription_id: subscription.id,
    },
    timestamp: new Date().toISOString(),
  }),
})
The userId must match the user who started checkout. This connects the server-side conversion to the browser-side session, pulling in preserved attribution.
4

Verify attribution preservation

Check your dashboard. The subscription_started event should include:
  • Original click IDs (gclid, fbclid)
  • First touch attribution from initial ad click
  • Last touch attribution from recent session
  • All UTM parameters
Our server enriches webhook events with the preserved user profile automatically.
Result: Attribution recovery starts immediately after deployment. Server enrichment happens automatically – no manual parameter passing required.

Web-to-App Flows

Timeline: 1-2 hours Common for: Dating apps, wellness platforms, fitness subscriptions with web signup → app usage

The challenge

Users sign up on web, then engage in mobile app. Without identity stitching, web browsing appears as one user and app activity as another. You can’t connect acquisition campaigns to in-app activation and retention.

How Fidero solves this

The server maintains a unified user profile across web and app. When users log in via either channel, we automatically stitch sessions into a single chronological journey.

Implementation

1

Install pixel on website

<script>
  fidero.load()
  fidero.init("YOUR_PROJECT_ID")
  fidero.page() // Captures initial visit, click IDs, anonymous browsing
</script>
Captures initial visit, click IDs and anonymous browsing behaviour.
2

Track signup on web

// When user completes signup form
fidero.track({
  event: "signup_completed",
  userId: "user_abc123", // CRITICAL: Creates unified user profile
  traits: {
    email: "alex@example.com",
    signup_source: "web",
  },
})
Creates unified user profile with web attribution context. This links all previous anonymous browsing to the known user.
3

Identify user in mobile app

// Server-side when user logs into app (first time or returning)
await fetch("https://api.fidero.com/v1/identify", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${FIDERO_API_KEY}`,
  },
  body: JSON.stringify({
    projectId: "YOUR_PROJECT_ID",
    userId: "user_abc123", // CRITICAL: Same ID as web signup for stitching
    traits: {
      app_version: "2.1.0",
      device: "iOS",
    },
  }),
})
Server automatically merges app session with web profile. This connects in-app behaviour to original acquisition source.
4

Track in-app events

// Server-side in-app events (e.g. profile completion, first workout, etc.)
await fetch("https://api.fidero.com/v1/track", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${FIDERO_API_KEY}`,
  },
  body: JSON.stringify({
    projectId: "YOUR_PROJECT_ID",
    userId: "user_abc123",
    event: "profile_completed",
    properties: {
      completion_percentage: 100,
    },
  }),
})
Event automatically includes:
  • Original acquisition source from web (e.g. TikTok, Google Ads)
  • First touch attribution from initial ad click
  • All web browsing context
  • Complete user journey timeline
Result: Product teams see “Users from TikTok campaign X have 45% higher activation rate in the app” – connecting acquisition source to in-app behaviour. Identity stitching happens in real-time as users log in.

Offline Conversions

Timeline: 30 minutes Common for: Webhook-based conversions, CRM events, delayed subscription confirmations

The challenge

Server-side conversions (webhooks, CRM updates, batch processing) lack browser context needed for attribution. You can’t connect these conversions to the original campaign.

How Fidero solves this

Server maintains complete user profile including attribution context. When you send a conversion event with a userId, we automatically enrich it with preserved context.

Implementation

1

Install pixel (captures initial context)

<script>
  fidero.load()
  fidero.init("YOUR_PROJECT_ID")
  fidero.page() // Captures click IDs and attribution when users first visit
</script>
Captures click IDs and attribution context when users first visit.
2

Track user identity

// Browser-side when they sign up (creates the unified profile)
fidero.track({
  event: "signup_completed",
  userId: "user_abc123", // Links anonymous browsing to known identity
  traits: {
    email: "alex@example.com",
  },
})
3

Send offline conversions via API

// Server-side webhook handler (days/weeks later)
await fetch("https://api.fidero.com/v1/track", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${FIDERO_API_KEY}`,
  },
  body: JSON.stringify({
    projectId: "YOUR_PROJECT_ID",
    userId: "user_abc123", // CRITICAL: Links to existing profile
    event: "subscription_started",
    properties: {
      transaction_id: "sub_xyz789", // CRITICAL: Deduplication
      value: 49.99,
      currency: "GBP",
      subscription_id: "sub_xyz789",
    },
    timestamp: new Date().toISOString(),
  }),
})
What gets enriched automatically:
  • Original click IDs (gclid, fbclid, ttclid)
  • First touch attribution (campaign, source, medium from initial visit)
  • Last touch attribution (most recent session context)
  • All user traits from unified profile
  • Complete user journey timeline
Result: Server-side conversions flow to Meta CAPI, Google Ads Offline Conversions and GA4 Measurement Protocol with complete attribution context. Works immediately for any user with an existing profile.

SPA Page Tracking

Timeline: 15 minutes Common for: React, Vue, Angular, Next.js applications

The challenge

Single-page applications change routes without full page reloads. The pixel tracks initial page view automatically – subsequent route changes aren’t captured unless you tell it.

Implementation

1

Install pixel normally

<script>
  fidero.load()
  fidero.init("YOUR_PROJECT_ID")
  fidero.page() // Captures first page view automatically
</script>
2

Call fidero.page() on route changes

React Router:
import { useEffect } from "react"
import { useLocation } from "react-router-dom"

function App() {
  const location = useLocation()

  useEffect(() => {
    // Track page view on every route change
    fidero.page()
  }, [location]) // Runs when location changes

  return <YourApp />
}
Next.js:
// pages/_app.js
import { useRouter } from "next/router"
import { useEffect } from "react"

function MyApp({ Component, pageProps }) {
  const router = useRouter()

  useEffect(() => {
    // Track page view when route changes
    const handleRouteChange = () => fidero.page()
    router.events.on("routeChangeComplete", handleRouteChange)

    // Cleanup listener on unmount
    return () => router.events.off("routeChangeComplete", handleRouteChange)
  }, [router.events])

  return <Component {...pageProps} />
}
Vue Router:
// In your router setup
router.afterEach(() => {
  // Track page view after each navigation
  fidero.page()
})
What this captures: Each fidero.page() call sends a page view with current URL, page title, referrer, session context and all preserved attribution data.

Next steps

After implementing your pattern: Within 24 hours: Attribution context flows to all destinations, user profiles unify across touchpoints, tools show consistent numbers Within 30 days: 85%+ attribution coverage, 90%+ cross-domain session linking, 95%+ consent enforcement