From 62c76f3738b13f013e00ffaf862ed0dcee5747cb Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 31 Jul 2026 05:13:19 +0000 Subject: [PATCH] fix(funnel): preserve selected credit pack through signup Co-authored-by: Deesmo --- api/public/pricing.html | 13 +++++++++--- api/src/assets/signupHtml.ts | 9 +++++--- api/src/index.ts | 8 +++---- api/src/utils/oauthNext.ts | 23 +++++++++++--------- api/tests/intent-funnel.test.mjs | 36 ++++++++++++++++++++++---------- 5 files changed, 58 insertions(+), 31 deletions(-) diff --git a/api/public/pricing.html b/api/public/pricing.html index 55d943ee..8858f81f 100644 --- a/api/public/pricing.html +++ b/api/public/pricing.html @@ -310,17 +310,24 @@

⭐ Featured

try { apiKey = (sessionStorage.getItem('arch_api_key') || localStorage.getItem('arch_api_key') || '').trim(); } catch(e) {} var headers = { 'Content-Type': 'application/json' }; if (apiKey) headers['Authorization'] = 'Bearer ' + apiKey; + function pricingNextForBody(payload) { + var pack = payload && payload.pack; + return (pack === 'starter' || pack === 'pro' || pack === 'business') + ? '/pricing?pack=' + pack + : '/pricing'; + } try { var res = await fetch(endpoint, { method: 'POST', headers: headers, credentials: 'include', body: JSON.stringify(body) }); if (res.status === 401) { + var next = pricingNextForBody(body); if (apiKey) { // A stored key failed — clear it and send them to sign back in. try { localStorage.removeItem('arch_api_key'); sessionStorage.removeItem('arch_api_key'); } catch(e) {} - window.location.href = '/login?next=' + encodeURIComponent('/pricing'); + window.location.href = '/login?next=' + encodeURIComponent(next); } else { // Anonymous buy-intent: they have no account to log into — send them to - // sign up (free), then return to pricing to complete the purchase. - window.location.href = '/signup?next=' + encodeURIComponent('/pricing'); + // sign up (free), then return to the selected pack to complete checkout. + window.location.href = '/signup?next=' + encodeURIComponent(next); } return; } diff --git a/api/src/assets/signupHtml.ts b/api/src/assets/signupHtml.ts index bb351318..c0ed154a 100644 --- a/api/src/assets/signupHtml.ts +++ b/api/src/assets/signupHtml.ts @@ -165,15 +165,18 @@ export const SIGNUP_HTML = ` // ?next= round-trips (server strips anything else too — this is defense // in depth; validated values are safe to embed in a double-quoted href): // - OAuth consent: /signup?next=/oauth/authorize?... resume-consent CTA. - // - Page intent: an EXACT allowlisted path (keys of PAGE_NEXT_LABELS, + // - Page intent: an EXACT allowlisted target (keys of PAGE_NEXT_LABELS, // mirroring utils/oauthNext.ts SIGNUP_NEXT_LABELS) renders a // "Continue to