Repository navigation
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Unconditional
console.errorcalls pollute customer browser consoles- Removed all three console.error calls in cookie operations (storeRedirectImpressions, fireStoredRedirectImpressions, and cleanup) and replaced them with silent failure as the cookie storage is a non-critical fallback mechanism.
Or push these changes by commenting:
@cursor push 9ead4e2377
Preview (9ead4e2377)
diff --git a/packages/experiment-tag/src/experiment.ts b/packages/experiment-tag/src/experiment.ts
--- a/packages/experiment-tag/src/experiment.ts
+++ b/packages/experiment-tag/src/experiment.ts
@@ -1179,11 +1179,8 @@
const redirects = storedRedirects || {};
redirects[flagKey] = impression;
await storage.set(storageKey, redirects);
- } catch (error) {
- console.error(
- `Failed to store redirect impression in cookie for ${flagKey}:`,
- error,
- );
+ } catch {
+ // Fail silently - cookie storage is a fallback mechanism
}
}
@@ -1225,11 +1222,8 @@
});
try {
cookieImpressions = (await cookieStorage.get(storageKey)) || {};
- } catch (error) {
- console.error(
- `Failed to retrieve redirect impressions from cookie ${storageKey}:`,
- error,
- );
+ } catch {
+ // Fail silently - cookie storage is a fallback mechanism
}
// Merge with priority: url > session > cookie
@@ -1261,11 +1255,8 @@
const cleanup = async () => {
removeStorageItem('sessionStorage', storageKey);
- await cookieStorage.remove(storageKey).catch((error) => {
- console.error(
- `Failed to remove redirect impressions from cookie ${storageKey}:`,
- error,
- );
+ await cookieStorage.remove(storageKey).catch(() => {
+ // Fail silently - cookie storage is a fallback mechanism
});
};You can send follow-ups to the cloud agent here.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Redirect config flags ignored
- Added guards checking
this.config.redirectConfig?.encodeRedirectInUrl !== falseandthis.config.redirectConfig?.encodeRedirectInCookie !== falseto respect explicit opt-out while maintaining default-enabled behavior.
- Added guards checking
Or push these changes by commenting:
@cursor push 9f8b10e1b1
Preview (9f8b10e1b1)
diff --git a/packages/experiment-tag/src/experiment.ts b/packages/experiment-tag/src/experiment.ts
--- a/packages/experiment-tag/src/experiment.ts
+++ b/packages/experiment-tag/src/experiment.ts
@@ -909,29 +909,33 @@
// Embed impression data in redirect URL for cross-domain and
// cookie-blocked environments. Merge with any existing param in case
// multiple redirect experiments fire in sequence.
- const targetUrlObj = new URL(targetUrl);
- let urlPayload: Record<string, StoredRedirectImpression> = {};
- const existingEncoded = targetUrlObj.searchParams.get(
- REDIRECT_IMPRESSION_PARAM,
- );
- if (existingEncoded) {
- try {
- urlPayload = JSON.parse(atob(existingEncoded));
- } catch (error) {
- console.error('Failed to decode existing AMP_REDIRECT param:', error);
+ if (this.config.redirectConfig?.encodeRedirectInUrl !== false) {
+ const targetUrlObj = new URL(targetUrl);
+ let urlPayload: Record<string, StoredRedirectImpression> = {};
+ const existingEncoded = targetUrlObj.searchParams.get(
+ REDIRECT_IMPRESSION_PARAM,
+ );
+ if (existingEncoded) {
+ try {
+ urlPayload = JSON.parse(atob(existingEncoded));
+ } catch (error) {
+ console.error('Failed to decode existing AMP_REDIRECT param:', error);
+ }
}
+ urlPayload[flagKey] = {
+ redirectUrl,
+ variantKey: variant.key || '',
+ ...(variant.expKey !== undefined ? { expKey: variant.expKey } : {}),
+ ...(variant.metadata !== undefined
+ ? { metadata: variant.metadata }
+ : {}),
+ };
+ targetUrlObj.searchParams.set(
+ REDIRECT_IMPRESSION_PARAM,
+ btoa(JSON.stringify(urlPayload)),
+ );
+ targetUrl = targetUrlObj.toString();
}
- urlPayload[flagKey] = {
- redirectUrl,
- variantKey: variant.key || '',
- ...(variant.expKey !== undefined ? { expKey: variant.expKey } : {}),
- ...(variant.metadata !== undefined ? { metadata: variant.metadata } : {}),
- };
- targetUrlObj.searchParams.set(
- REDIRECT_IMPRESSION_PARAM,
- btoa(JSON.stringify(urlPayload)),
- );
- targetUrl = targetUrlObj.toString();
// set previous url - relevant for SPA if redirect happens before push/replaceState is complete
this.previousUrl = this.globalScope.location.href;
@@ -1169,25 +1173,29 @@
setStorageItem('sessionStorage', storageKey, stored);
// Also write to cookie to enable cross-subdomain tracking
- const domain = await getTopLevelDomain(this.globalScope.location.hostname);
- const storage = new CookieStorage<Record<string, StoredRedirectImpression>>(
- {
+ if (this.config.redirectConfig?.encodeRedirectInCookie !== false) {
+ const domain = await getTopLevelDomain(
+ this.globalScope.location.hostname,
+ );
+ const storage = new CookieStorage<
+ Record<string, StoredRedirectImpression>
+ >({
...(domain && { domain }),
sameSite: 'Lax',
expirationDays: 1 / 1440, // 1 minute
- },
- );
+ });
- try {
- const storedRedirects = await storage.get(storageKey);
- const redirects = storedRedirects || {};
- redirects[flagKey] = impression;
- await storage.set(storageKey, redirects);
- } catch (error) {
- console.error(
- `Failed to store redirect impression in cookie for ${flagKey}:`,
- error,
- );
+ try {
+ const storedRedirects = await storage.get(storageKey);
+ const redirects = storedRedirects || {};
+ redirects[flagKey] = impression;
+ await storage.set(storageKey, redirects);
+ } catch (error) {
+ console.error(
+ `Failed to store redirect impression in cookie for ${flagKey}:`,
+ error,
+ );
+ }
}
}You can send follow-ups to the cloud agent here.
528f239 to
ce31466
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Redirect stall hangs startup
- Removed the never-resolving promise after location.replace() and replaced it with a simple return statement, allowing startup to complete normally when navigation doesn't occur immediately.
Or push these changes by commenting:
@cursor push cc22a41767
Preview (cc22a41767)
diff --git a/packages/experiment-tag/src/experiment.ts b/packages/experiment-tag/src/experiment.ts
--- a/packages/experiment-tag/src/experiment.ts
+++ b/packages/experiment-tag/src/experiment.ts
@@ -999,10 +999,7 @@
return;
}
this.globalScope.location.replace(targetUrl);
- // location.replace() queues navigation but JS continues — stall so applyVariants
- // never resolves and removeAntiFlickerCss() is never called during the unload window.
- // eslint-disable-next-line @typescript-eslint/no-empty-function
- await new Promise(() => {});
+ return;
}
private handleMutate(action, flagKey: string, variant: Variant) {You can send follow-ups to the cloud agent here.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Custom redirect skips remote flags
- Moved isRedirecting = true to only execute after the custom handler check, ensuring SPAs using custom redirect handlers will continue to fetch remote flags after client-side navigation.
Or push these changes by commenting:
@cursor push ba7cf0cad9
Preview (ba7cf0cad9)
diff --git a/packages/experiment-tag/src/experiment.ts b/packages/experiment-tag/src/experiment.ts
--- a/packages/experiment-tag/src/experiment.ts
+++ b/packages/experiment-tag/src/experiment.ts
@@ -995,14 +995,18 @@
// set previous url - relevant for SPA if redirect happens before push/replaceState is complete
this.previousUrl = this.globalScope.location.href;
await setMarketingCookie(this.apiKey, this.globalScope.location.hostname);
- // Mark redirect as in-flight so start() skips removeAntiFlickerCss and
- // further processing after applyVariants returns.
- this.isRedirecting = true;
// perform redirection
if (this.customRedirectHandler) {
+ // Custom redirect handlers may perform client-side routing without a
+ // page reload, so we should NOT set isRedirecting. This allows start()
+ // to continue and fetch remote flags after the SPA navigation.
this.customRedirectHandler(targetUrl);
return;
}
+ // Mark redirect as in-flight so start() skips removeAntiFlickerCss and
+ // further processing after applyVariants returns. Only set for full-page
+ // navigation since the page will unload anyway.
+ this.isRedirecting = true;
this.globalScope.location.replace(targetUrl);
}You can send follow-ups to the cloud agent here.
Reviewed by Cursor Bugbot for commit 27bd6d0. Configure here.
size-limit report 📦
|
6cdd9f3 to
2b5a632
Compare


Summary
Branch script to use cookie+urlParam-based fallback for redirect actions by default.
Checklist
Note
Medium Risk
Changing a public default alters redirect impression tracking and destination URLs for customers who do not override
redirectConfig, with possible visibility ofAMP_REDIRECTon landing URLs.Overview
Default redirect config now sets
encodeRedirectInUrl: trueinDefaults(cookie encoding was already on). Redirect actions therefore use cookie +AMP_REDIRECTURL param fallback out of the box, matching the branch script behavior described in the PR.For cross-subdomain redirects, impression data is embedded in the destination URL when this flag is true (unchanged logic—only the default flipped). Integrations that relied on the old default and did not set
redirectConfigwill start seeing query-param transport unless they explicitly setencodeRedirectInUrl: false.Reviewed by Cursor Bugbot for commit 2b5a632. Bugbot is set up for automated code reviews on this repo. Configure here.