Skip to content

feat: pass shopper consent to checkout#2666

Merged
chanceaclark merged 1 commit intocanaryfrom
feat/pass-consent-to-checkout
Nov 10, 2025
Merged

feat: pass shopper consent to checkout#2666
chanceaclark merged 1 commit intocanaryfrom
feat/pass-consent-to-checkout

Conversation

@chanceaclark
Copy link
Copy Markdown
Contributor

@chanceaclark chanceaclark commented Oct 31, 2025

What/Why?

This pull request enhances the checkout redirect flow by passing shopper consent preferences to the checkout redirect mutation. Previously, the checkout redirect only included basic cart and visitor information (cartId, visitId, visitorId). This update extends the mutation to include comprehensive analytics data, including:

  • Consent preferences: Analytics, functional, and targeting consent flags based on the shopper's consent manager preferences
  • Request context: Referer URL and user agent information for better tracking and analytics
  • Visitor identification: Visit ID and visitor ID (now passed as part of the analytics initiator structure)

Technical Details

The CheckoutRedirectMutation GraphQL mutation has been expanded to accept additional parameters:

  • referer (URL): The referring page URL from the request headers
  • userAgent (String): The user agent string from the request headers
  • analyticsConsent, functionalConsent, targetingConsent (Boolean): Consent preferences derived from the consent manager cookie

These parameters are passed through a new analytics object structure in the mutation input, which includes:

  • initiator: Contains visitId and visitorId for visitor tracking
  • request: Contains url (referer) and userAgent for request context
  • consent: Contains the three consent preference flags

The implementation retrieves consent preferences from the consent manager cookie using getConsentCookie() and maps them to the appropriate checkout analytics fields:

  • measurementanalyticsConsent
  • functionalityfunctionalConsent
  • marketingtargetingConsent

All new required fields use sensible fallback values (empty strings for missing headers, false for undefined consent preferences) to ensure the mutation always has valid data.

Testing

Even though there are no new fields on the session_payload, the visit_id and visitor_id fields are being pass from the new analytics object.
Screenshot 2025-10-31 at 16 56 47

Migration

No migration required. This is a backward-compatible enhancement to the checkout flow. The changes are contained within the checkout route handler and do not affect existing functionality or require updates to other parts of the codebase.


This pull request description was generated with the assistance of AI. Portions of the code and/or implementation ideas in this PR may also have been created or influenced by AI tools.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Oct 31, 2025

🦋 Changeset detected

Latest commit: 33820ab

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@bigcommerce/catalyst-core Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link
Copy Markdown

vercel Bot commented Oct 31, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
catalyst-b2b Ready Ready Preview Comment Nov 10, 2025 6:20pm
catalyst-canary Ready Ready Preview Comment Nov 10, 2025 6:20pm
1 Skipped Deployment
Project Deployment Preview Comments Updated (UTC)
catalyst Ignored Ignored Nov 10, 2025 6:20pm

@chanceaclark chanceaclark marked this pull request as ready for review October 31, 2025 22:58
@chanceaclark chanceaclark requested a review from a team October 31, 2025 22:58
analyticsConsent: consent?.preferences.measurement ?? false,
functionalConsent: consent?.preferences.functionality ?? false,
targetingConsent: consent?.preferences.marketing ?? false,
referer: req.headers.get('referer') ?? '',
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: Empty string fallback for referer will fail GraphQL URL! scalar validation, blocking checkout.
Severity: HIGH | Confidence: 0.85

🔍 Detailed Analysis

The code passes an empty string ('') as a fallback for the referer header via req.headers.get('referer') ?? ''. This value is then used in a GraphQL mutation that expects a $referer: URL! scalar type. Standard GraphQL URL scalar types strictly validate URLs and will reject an empty string as invalid. This will cause a GraphQL validation error, preventing the checkout redirect mutation from completing and users from proceeding with checkout when the HTTP referer header is missing.

💡 Suggested Fix

Change the $referer GraphQL argument to String!, make it optional (URL), or provide a valid fallback URL (e.g., site's base URL) instead of an empty string.

🤖 Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: core/app/[locale]/(default)/checkout/route.ts#L77

Potential issue: The code passes an empty string (`''`) as a fallback for the `referer`
header via `req.headers.get('referer') ?? ''`. This value is then used in a GraphQL
mutation that expects a `$referer: URL!` scalar type. Standard GraphQL URL scalar types
strictly validate URLs and will reject an empty string as invalid. This will cause a
GraphQL validation error, preventing the checkout redirect mutation from completing and
users from proceeding with checkout when the HTTP referer header is missing.

Did we get this right? 👍 / 👎 to inform future reviews.

Copy link
Copy Markdown
Contributor

@matthewvolk matthewvolk left a comment

Choose a reason for hiding this comment

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

I wonder if I can make a better abstraction for mapping between our consent category names vs. the libraries... or if that's even worth it.

@chanceaclark
Copy link
Copy Markdown
Contributor Author

I wonder if I can make a better abstraction for mapping between our consent category names vs. the libraries... or if that's even worth it.

Let's definitely think about this more. As I was working on this, I really liked how simple the categories c15t used as our based consent values. But other analytics providers and our own API have their own mappings which we need to account for. Again, let's keep thinking about this a bit more.

@chanceaclark
Copy link
Copy Markdown
Contributor Author

Applying do not merge as we need the FF to be enabled before this goes out. Waiting on @jordanarldt's work to go through beforehand.

@chanceaclark chanceaclark force-pushed the feat/pass-consent-to-checkout branch from 9c283af to 33820ab Compare November 10, 2025 18:19
@chanceaclark chanceaclark added this pull request to the merge queue Nov 10, 2025
Merged via the queue into canary with commit ed1f615 Nov 10, 2025
11 checks passed
@chanceaclark chanceaclark deleted the feat/pass-consent-to-checkout branch November 10, 2025 18:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants