Skip to content

feat: add checkout attribution telemetry#8688

Open
benceruleanlu wants to merge 2 commits intomainfrom
feat/checkout-attribution-journey
Open

feat: add checkout attribution telemetry#8688
benceruleanlu wants to merge 2 commits intomainfrom
feat/checkout-attribution-journey

Conversation

@benceruleanlu
Copy link
Member

@benceruleanlu benceruleanlu commented Feb 6, 2026

Summary

Persist checkout attribution metadata across cloud page views and include it in subscription checkout requests so affiliate/ad attribution survives multi-page journeys.

Changes

  • What: Add CheckoutAttributionTelemetryProvider and register it in telemetry init so page views capture attribution query params (with current-URL fallback).
  • What: Extend checkout attribution types/utilities to support im_ref, UTM fields, gclid/gbraid/wbraid, and impact_click_id.
  • What: Avoid redundant localStorage writes when incoming attribution matches stored values.
  • What: Send merged checkout attribution metadata in /customers/cloud-subscription-checkout request bodies.
  • What: Add/update tests for checkout payload contents and attribution capture/persistence behavior.

Review Focus

  • Confirm URL vs stored attribution merge behavior and deduplicated persistence logic.
  • Confirm checkout request payload shape is correct and backend-compatible for optional attribution fields.

Screenshots (if applicable)

N/A (no UI changes)

@benceruleanlu benceruleanlu requested a review from a team as a code owner February 6, 2026 05:24
Copilot AI review requested due to automatic review settings February 6, 2026 05:24
@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Feb 6, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 6, 2026

📝 Walkthrough

Walkthrough

This change implements checkout attribution tracking across the platform by introducing a new telemetry provider that captures attribution metadata from URL query parameters, persists it to storage, and plumbs it into subscription checkout requests. The changes extend metadata types and integrate attribution retrieval into the checkout flow.

Changes

Cohort / File(s) Summary
Telemetry Provider & Types
src/platform/telemetry/providers/cloud/CheckoutAttributionTelemetryProvider.ts, src/platform/telemetry/types.ts, src/platform/telemetry/initTelemetry.ts
New CheckoutAttributionTelemetryProvider class intercepts page views to capture attribution from query parameters; BeginCheckoutMetadata extended with CheckoutAttributionMetadata fields (ga_client_id, im_ref, utm_source, etc.); provider registered in telemetry initialization.
Attribution Utilities
src/platform/telemetry/utils/checkoutAttribution.ts, src/platform/telemetry/utils/__tests__/checkoutAttribution.test.ts
New exported function captureCheckoutAttributionFromSearch() captures and persists attribution data to storage; CheckoutAttribution type now aliases CheckoutAttributionMetadata; expanded test coverage for attribution capture and storage interactions.
Subscription Checkout Integration
src/platform/cloud/subscription/composables/useSubscription.ts, src/platform/cloud/subscription/composables/useSubscription.test.ts, src/platform/cloud/subscription/utils/subscriptionCheckoutUtil.test.ts
Checkout flow calls getCheckoutAttribution() and includes attribution data in subscription checkout request body; test mocks and expectations updated to verify attribution fields (im_ref, impact_click_id, utm_source) are passed through telemetry and network payloads.

Sequence Diagram

sequenceDiagram
    participant Browser as Browser/Page View
    participant TelemetryProvider as CheckoutAttributionTelemetryProvider
    participant Attribution as checkoutAttribution Util
    participant Storage as Local Storage
    participant Checkout as Subscription Checkout

    Browser->>TelemetryProvider: trackPageView() with search params
    TelemetryProvider->>TelemetryProvider: extractSearchFromPath() or use window.location.search
    TelemetryProvider->>Attribution: captureCheckoutAttributionFromSearch(search)
    Attribution->>Attribution: Parse attribution fields from query params
    Attribution->>Storage: Persist attribution to localStorage
    
    Note over Browser,Storage: User initiates checkout
    
    Checkout->>Attribution: getCheckoutAttribution()
    Attribution->>Storage: Read persisted attribution
    Attribution->>Checkout: Return attribution object
    Checkout->>Checkout: Include attribution in request body
    Checkout->>Browser: Send checkout request with attribution fields
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 Attribution now flows through our pipes so clean,
From query strings to storage, a telemetry dream!
Checkout fields enriched with utm and gclid,
The rabbit hops forward, attribution well-hid! 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main feature being added: checkout attribution telemetry for persisting affiliate/ad attribution across cloud page views and checkout requests.
Description check ✅ Passed The description includes all required template sections with substantive content: a clear summary statement, detailed changes with 'What' bullets, and explicit review focus areas. It comprehensively documents the feature scope and implementation approach.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/checkout-attribution-journey

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Feb 6, 2026

🎨 Storybook Build Status

Build completed successfully!

⏰ Completed at: 02/08/2026, 04:41:58 AM UTC

🔗 Links


🎉 Your Storybook is ready for review!

@github-actions
Copy link

github-actions bot commented Feb 6, 2026

🎭 Playwright Tests: ❌ Failed

Results: 513 passed, 1 failed, 4 flaky, 8 skipped (Total: 526)

❌ Failed Tests

📊 Browser Reports
  • chromium: View Report (✅ 501 / ❌ 1 / ⚠️ 4 / ⏭️ 8)
  • chromium-2x: View Report (✅ 2 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • chromium-0.5x: View Report (✅ 1 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • mobile-chrome: View Report (✅ 9 / ❌ 0 / ⚠️ 0 / ⏭️ 0)

Copy link
Member Author

benceruleanlu commented Feb 6, 2026

This stack of pull requests is managed by Graphite. Learn more about stacking.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds comprehensive checkout attribution tracking to capture marketing attribution data (UTM parameters, Impact affiliate tracking, and Google Ads click IDs) during user sessions. The attribution data is persisted to localStorage, captured on page views via a dedicated telemetry provider, and sent to the backend during subscription checkout flows.

Changes:

  • Expanded attribution tracking from just Google Ads click IDs (gclid, gbraid, wbraid) to include UTM parameters and Impact affiliate tracking (im_ref)
  • Added a new CheckoutAttributionTelemetryProvider that captures attribution data on page views
  • Modified subscription checkout flows to send attribution data to the backend API

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/platform/telemetry/utils/checkoutAttribution.ts Core attribution logic: renamed functions/types, added UTM and Impact tracking, added deduplication logic to prevent unnecessary storage writes
src/platform/telemetry/utils/tests/checkoutAttribution.test.ts Comprehensive test coverage for attribution capture, storage, and deduplication scenarios
src/platform/telemetry/types.ts New CheckoutAttributionMetadata interface with all attribution fields, extended BeginCheckoutMetadata
src/platform/telemetry/providers/cloud/CheckoutAttributionTelemetryProvider.ts New telemetry provider that captures attribution from page view paths
src/platform/telemetry/initTelemetry.ts Registered new CheckoutAttributionTelemetryProvider in telemetry initialization
src/platform/cloud/subscription/utils/subscriptionCheckoutUtil.test.ts Updated tests with new attribution fields
src/platform/cloud/subscription/composables/useSubscription.ts Modified initiateSubscriptionCheckout to send attribution data in request body
src/platform/cloud/subscription/composables/useSubscription.test.ts Added mock for getCheckoutAttribution and verified attribution is sent in checkout requests

Comment on lines +1 to +34
import { captureCheckoutAttributionFromSearch } from '@/platform/telemetry/utils/checkoutAttribution'

import type { PageViewMetadata, TelemetryProvider } from '../../types'

/**
* Internal cloud telemetry provider used to persist checkout attribution
* from query parameters during page view tracking.
*/
export class CheckoutAttributionTelemetryProvider implements TelemetryProvider {
trackPageView(_pageName: string, properties?: PageViewMetadata): void {
const search = this.extractSearchFromPath(properties?.path)

if (search) {
captureCheckoutAttributionFromSearch(search)
return
}

if (typeof window !== 'undefined') {
captureCheckoutAttributionFromSearch(window.location.search)
}
}

private extractSearchFromPath(path?: string): string {
if (!path || typeof window === 'undefined') return ''

try {
const url = new URL(path, window.location.origin)
return url.search
} catch {
const queryIndex = path.indexOf('?')
return queryIndex >= 0 ? path.slice(queryIndex) : ''
}
}
}
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CheckoutAttributionTelemetryProvider lacks test coverage. While the underlying captureCheckoutAttributionFromSearch function is well-tested, the provider's specific behavior should also be tested, particularly:

  1. The extractSearchFromPath method with various path formats
  2. The fallback to window.location.search when no path is provided
  3. Integration with the trackPageView lifecycle

This is important because the provider has its own logic for extracting search parameters from paths and choosing between the provided path and window.location.search.

Copilot uses AI. Check for mistakes.
@benceruleanlu benceruleanlu force-pushed the fix/distribution-only-desktop branch from a8df879 to e38875c Compare February 7, 2026 09:16
@benceruleanlu benceruleanlu force-pushed the feat/checkout-attribution-journey branch from 0f32622 to dafccab Compare February 7, 2026 09:16
@benceruleanlu benceruleanlu changed the base branch from fix/distribution-only-desktop to graphite-base/8688 February 7, 2026 09:16
@benceruleanlu benceruleanlu force-pushed the feat/checkout-attribution-journey branch from dafccab to 4fb386d Compare February 7, 2026 10:00
@benceruleanlu benceruleanlu changed the base branch from graphite-base/8688 to fix/distribution-only-desktop February 7, 2026 10:00
@benceruleanlu benceruleanlu changed the base branch from fix/distribution-only-desktop to graphite-base/8688 February 8, 2026 04:40
@benceruleanlu benceruleanlu force-pushed the feat/checkout-attribution-journey branch from 4fb386d to 73c0451 Compare February 8, 2026 04:40
@benceruleanlu benceruleanlu changed the base branch from graphite-base/8688 to main February 8, 2026 04:40
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@src/platform/telemetry/providers/cloud/CheckoutAttributionTelemetryProvider.ts`:
- Around line 23-33: The SSR guard currently returns early in
extractSearchFromPath and blocks the manual fallback; instead ensure you only
early-return when path is falsy, then attempt to construct new URL only if
typeof window !== 'undefined' (wrap new URL in try/catch), and if window is
undefined or URL construction fails fall back to using path.indexOf('?') to
slice and return the query string; update extractSearchFromPath to perform path
check first, then try the window-dependent URL parsing, and finally the manual
indexOf fallback.

Comment on lines +23 to +33
private extractSearchFromPath(path?: string): string {
if (!path || typeof window === 'undefined') return ''

try {
const url = new URL(path, window.location.origin)
return url.search
} catch {
const queryIndex = path.indexOf('?')
return queryIndex >= 0 ? path.slice(queryIndex) : ''
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

SSR guard on Line 24 also blocks the window-independent fallback path.

When window is undefined but a valid path with query params is provided (e.g. "/checkout?utm_source=google"), the early return on Line 24 prevents reaching the manual indexOf('?') fallback (lines 30–31), which doesn't need window at all. This silently drops attribution params in SSR/test environments.

Move the window guard to only protect the new URL call:

Suggested fix
  private extractSearchFromPath(path?: string): string {
-   if (!path || typeof window === 'undefined') return ''
+   if (!path) return ''

    try {
+     if (typeof window === 'undefined') throw new Error('no window')
      const url = new URL(path, window.location.origin)
      return url.search
    } catch {
      const queryIndex = path.indexOf('?')
      return queryIndex >= 0 ? path.slice(queryIndex) : ''
    }
  }
🤖 Prompt for AI Agents
In
`@src/platform/telemetry/providers/cloud/CheckoutAttributionTelemetryProvider.ts`
around lines 23 - 33, The SSR guard currently returns early in
extractSearchFromPath and blocks the manual fallback; instead ensure you only
early-return when path is falsy, then attempt to construct new URL only if
typeof window !== 'undefined' (wrap new URL in try/catch), and if window is
undefined or URL construction fails fall back to using path.indexOf('?') to
slice and return the query string; update extractSearchFromPath to perform path
check first, then try the window-dependent URL parsing, and finally the manual
indexOf fallback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants