Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 17 additions & 8 deletions packages/experiment-tag/src/experiment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ import {
ConsentAwareStorage,
} from './storage/consent-aware-storage';
import {
getExperimentStorageKey,
getPreviewModeSessionKey,
getRedirectStorageKey,
getVisualEditorSessionKey,
} from './storage/keys';
import {
deletePersistedData,
getAndParseStorageItem,
setAndStringifyStorageItem,
} from './storage/storage';
Expand All @@ -46,7 +53,7 @@ import {
} from './types';
import { applyAntiFlickerCss } from './util/anti-flicker';
import { getInjectUtils } from './util/inject-utils';
import { VISUAL_EDITOR_SESSION_KEY, WindowMessenger } from './util/messenger';
import { WindowMessenger } from './util/messenger';
import { patchRemoveChild } from './util/patch';
import {
getUrlParams,
Expand All @@ -62,7 +69,6 @@ const MUTATE_ACTION = 'mutate';
export const INJECT_ACTION = 'inject';
const REDIRECT_ACTION = 'redirect';
export const PREVIEW_MODE_PARAM = 'PREVIEW';
export const PREVIEW_MODE_SESSION_KEY = 'amp-preview-mode';
const VISUAL_EDITOR_PARAM = 'VISUAL_EDITOR';

safeGlobal.Experiment = FeatureExperiment;
Expand Down Expand Up @@ -200,7 +206,7 @@ export class DefaultWebExperimentClient implements WebExperimentClient {
const urlParams = getUrlParams();
this.isVisualEditorMode =
urlParams[VISUAL_EDITOR_PARAM] === 'true' ||
this.storage.getItem('sessionStorage', VISUAL_EDITOR_SESSION_KEY) !==
this.storage.getItem('sessionStorage', getVisualEditorSessionKey()) !==
null;
this.subscriptionManager = new SubscriptionManager(
this,
Expand Down Expand Up @@ -234,7 +240,7 @@ export class DefaultWebExperimentClient implements WebExperimentClient {
// fire url_change upon landing on page, set updateActivePagesOnly to not trigger variant actions
this.messageBus.publish('url_change', { updateActivePages: true });

const experimentStorageName = `EXP_${this.apiKey.slice(0, 10)}`;
const experimentStorageName = getExperimentStorageKey(this.apiKey);
const user =
this.storage.getItem<WebExperimentUser>(
'localStorage',
Expand Down Expand Up @@ -554,6 +560,9 @@ export class DefaultWebExperimentClient implements WebExperimentClient {
public setConsentStatus(consentStatus: ConsentStatus) {
this.consentOptions.status = consentStatus;
this.storage.setConsentStatus(consentStatus);
if (consentStatus === ConsentStatus.REJECTED) {
deletePersistedData(this.apiKey, this.config);
}
this.consentAwareExposureHandler.setConsentStatus(consentStatus);
}

Expand Down Expand Up @@ -829,7 +838,7 @@ export class DefaultWebExperimentClient implements WebExperimentClient {
variant: Variant,
redirectUrl: string,
) {
const redirectStorageKey = `EXP_${this.apiKey.slice(0, 10)}_REDIRECT`;
const redirectStorageKey = getRedirectStorageKey(this.apiKey);
// Store the current flag and variant for exposure tracking after redirect
const storedRedirects =
this.storage.getItem('sessionStorage', redirectStorageKey) || {};
Expand All @@ -839,7 +848,7 @@ export class DefaultWebExperimentClient implements WebExperimentClient {

private fireStoredRedirectImpressions() {
// Check for stored redirects and process them
const redirectStorageKey = `EXP_${this.apiKey.slice(0, 10)}_REDIRECT`;
const redirectStorageKey = getRedirectStorageKey(this.apiKey);
const storedRedirects =
this.storage.getItem('sessionStorage', redirectStorageKey) || {};

Expand Down Expand Up @@ -892,7 +901,7 @@ export class DefaultWebExperimentClient implements WebExperimentClient {

setAndStringifyStorageItem<PreviewState>(
'sessionStorage',
PREVIEW_MODE_SESSION_KEY,
getPreviewModeSessionKey(),
{
previewFlags: this.previewFlags,
},
Expand All @@ -914,7 +923,7 @@ export class DefaultWebExperimentClient implements WebExperimentClient {
} else {
const previewState = getAndParseStorageItem<PreviewState>(
'sessionStorage',
PREVIEW_MODE_SESSION_KEY,
getPreviewModeSessionKey(),
);
if (previewState) {
this.previewFlags = previewState.previewFlags;
Expand Down
2 changes: 2 additions & 0 deletions packages/experiment-tag/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { getGlobalScope } from '@amplitude/experiment-core';
import { DefaultWebExperimentClient } from './experiment';
import { HttpClient } from './preview/http';
import { SdkPreviewApi } from './preview/preview-api';
import { deletePersistedData } from './storage/storage';
import { ConsentStatus, WebExperimentConfig } from './types';
import { applyAntiFlickerCss } from './util/anti-flicker';
import { isPreviewMode } from './util/url';
Expand All @@ -17,6 +18,7 @@ export const initialize = (
getGlobalScope()?.experimentConfig?.consentOptions?.status ===
ConsentStatus.REJECTED
) {
deletePersistedData(apiKey, config);
return;
}
const shouldFetchConfigs =
Expand Down
27 changes: 27 additions & 0 deletions packages/experiment-tag/src/storage/keys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { WebExperimentConfig } from '../types';

export const getExperimentStorageKey = (apiKey: string): string => {
return `EXP_${apiKey.slice(0, 10)}`;
};

export const getDefaultUserProviderStorageKey = (apiKey: string): string => {
return `EXP_${apiKey.slice(0, 10)}_DEFAULT_USER_PROVIDER`;
};

export const getUnsentEventsStorageKey = (
config: WebExperimentConfig,
): string => {
return `EXP_unsent_${config.instanceName ?? 'default_instance'}`;
};

export const getRedirectStorageKey = (apiKey: string): string => {
return `EXP_${apiKey.slice(0, 10)}_REDIRECT`;
};

export const getPreviewModeSessionKey = (): string => {
return 'amp-preview-mode';
};

export const getVisualEditorSessionKey = (): string => {
return 'visual-editor-state';
};
22 changes: 22 additions & 0 deletions packages/experiment-tag/src/storage/storage.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { getGlobalScope } from '@amplitude/experiment-core';

import { WebExperimentConfig } from '../types';

import {
getDefaultUserProviderStorageKey,
getExperimentStorageKey,
getUnsentEventsStorageKey,
} from './keys';

export type StorageType = 'localStorage' | 'sessionStorage';

/**
Expand Down Expand Up @@ -77,3 +85,17 @@ const getStorage = (storageType: StorageType): Storage | null => {
}
return globalScope[storageType];
};

export const deletePersistedData = (
apiKey: string,
config: WebExperimentConfig,
): void => {
const experimentStorageKey = getExperimentStorageKey(apiKey);
const defaultUserProviderStorageKey =
getDefaultUserProviderStorageKey(apiKey);
const unsentEventsStorageKey = getUnsentEventsStorageKey(config);
removeStorageItem('localStorage', experimentStorageKey);
removeStorageItem('localStorage', defaultUserProviderStorageKey);
removeStorageItem('sessionStorage', defaultUserProviderStorageKey);
removeStorageItem('localStorage', unsentEventsStorageKey);
};
8 changes: 3 additions & 5 deletions packages/experiment-tag/src/util/messenger.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { getGlobalScope } from '@amplitude/experiment-core';

import { getVisualEditorSessionKey } from '../storage/keys';
import { getAndParseStorageItem } from '../storage/storage';

interface VisualEditorSession {
injectSrc: string;
amplitudeWindowUrl: string;
}

export const VISUAL_EDITOR_SESSION_KEY = 'visual-editor-state';

export class WindowMessenger {
static setup() {
let state: 'closed' | 'opening' | 'open' = 'closed';
Expand Down Expand Up @@ -75,9 +74,8 @@ export class WindowMessenger {
private static getStoredSession(): VisualEditorSession | null {
const sessionData = getAndParseStorageItem<VisualEditorSession>(
'sessionStorage',
VISUAL_EDITOR_SESSION_KEY,
) as VisualEditorSession;

getVisualEditorSessionKey(),
);
if (!sessionData) {
return null;
}
Expand Down
5 changes: 3 additions & 2 deletions packages/experiment-tag/src/util/url.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { getGlobalScope } from '@amplitude/experiment-core';

import { PREVIEW_MODE_PARAM, PREVIEW_MODE_SESSION_KEY } from '../experiment';
import { PREVIEW_MODE_PARAM } from '../experiment';
import { getPreviewModeSessionKey } from '../storage/keys';
import { getAndParseStorageItem } from '../storage/storage';
import { PreviewState } from '../types';

Expand Down Expand Up @@ -90,7 +91,7 @@ export const isPreviewMode = (): boolean => {
}
const previewState = getAndParseStorageItem<PreviewState>(
'sessionStorage',
PREVIEW_MODE_SESSION_KEY,
getPreviewModeSessionKey(),
);
if (!previewState) {
return false;
Expand Down