Storage Service
In-Built Storage
In browser-based environments, the VWO FE JavaScript SDK automatically utilizes the browser’s localStorage API to persist user-related data. This ensures a seamless user experience by maintaining state across page reloads and browser sessions.
Key Benefits of Custom Storage:
- Performance Optimization: Cache feature flag and variation decisions locally, reducing round trips to remote APIs.
- Consistency Across Sessions: Maintain stable experiences for returning users by preserving decision state.
- Reduced Backend/API Load: Avoid repeated decision evaluations by storing results on the client side.
Default Behavior
By default:
- The SDK leverages window.localStorage to persist all relevant data such as:
- User variation assignments
- Campaign and experiment metadata
- Event tracking identifiers
- This persistence ensures that:
-
Data survives browser restarts and page reloads
User consistency is maintained without requiring re-identification
-
- All data is stored under a key namespace prefixed with vwo_ for easy identification and isolation.
Customizing Storage: clientStorage Option
For more advanced use cases, the SDK provides a clientStorage configuration option during initialization. This allows you to override the default storage mechanism with a custom implementation.
flowchart TD
A[SDK Initialization] --> B[clientStorage option passed]
B --> C{isDisabled == true?}
C -- Yes --> D[Skip all storage; SDK operates statelessly]
C -- No --> E{provider defined?}
E -- Yes --> F[Use custom provider e.g. sessionStorage]
E -- No --> G[Use default: localStorage]
F & G --> H[Store data under specified key; default is vwo_fme_data]
Usage
const vwoClient = await init({
accountId: '123456',
sdkKey: '32-alpha-numeric-sdk-key',
clientStorage: {
// Custom key used to store SDK data, default is 'vwo_fme_data'
key: 'vwo_data',
// Storage mechanism to use: can be sessionStorage or localStorage (default)
provider: sessionStorage,
// If true, disables client-side in-built storage altogether. Though can connect Storage Connector still
isDisabled: false,
},
});Explanation of clientStorage Parameters
clientStorage ParametersParameter | Description | Use case | Default Value |
|---|---|---|---|
key(String) (Optional) | Specifies the key under which SDK data will be stored in browser storage. This allows you to customize the storage entry name to avoid conflicts or better organize stored data. | Useful for avoiding key collisions or aligning with your app's naming conventions. |
|
provider(Object) (Optional) | Determines the browser storage mechanism to use. It can be either |
|
|
isDisabled(Boolean) | When set to | Ideal for ephemeral or stateless environments, or when you need full control over state management externally. |
|
Important Notes
- Browser Environment Only: The
clientStorageoption works exclusively in browser environments wherelocalStorageandsessionStorageAPIs are available.- Node.js Environments: For server-side or Node.js environments, use the
storageoption for implementing custom storage logic, aslocalStorageandsessionStorageare not available there. To know more, click here.
How to Implement a Custom Storage Connector
In browser environments, if you prefer not to rely on VWO's default web-based APIs for decision resolution, you can still implement a custom storage connector. This gives you more control over how feature flag decisions are cached and reused, though it may introduce slight performance trade-offs depending on your implementation.
The storage mechanism ensures that once a decision is made for a user, it remains consistent even if campaign settings are modified in the VWO Application. This is particularly useful for maintaining a stable user experience during A/B tests and feature rollouts.
Usage
class StorageConnector extends StorageConnector {
protected ttl = 7200000; // 2 hours in milliseconds
protected alwaysUseCachedSettings = false;
constructor() {
super();
}
/**
* Get data from storage
* @param {string} featureKey
* @param {string} userId
* @returns {Promise<any>}
*/
async get(featureKey, userId) {
// return await data (based on featureKey and userId)
}
/**
* Set data in storage
* @param {object} data
*/
async set(data) {
// Set data corresponding to a featureKey and user ID
// Use data.featureKey and data.userId to store the above data for a specific feature and a user
}
/**
* Get settingsData from storage
* @param {number} accountId
* @param {string} sdkKey
* @returns {Promise<ISettingsData>}
*/
async getSettings(accountId, sdkKey) {
// Implement logic to retrieve cached settings based on accountId and sdkKey
// Must return an object with structure: { settings: {...}, timestamp: number }
}
/**
* Set settingsData in storage
* @param {ISettingsData} data
*/
async setSettings(data) {
// Implement logic to store settings data
// Use data.settings.accountId and data.settings.sdkKey to store the above data for a specific accountId and sdkKey
}
}
vwoSdk.init({
sdkKey: '...',
accountId: '123456',
storage: new StorageConnector(),
});Required Methods (Variation Storage)
Storage Service should expose two methods: get and set. These methods are used by VWO whenever there is a need to read from or write to the storage service.
| Method Name | Params | Description | Returns |
|---|---|---|---|
| get | featureKey, userId | Retrieve stored data corresponding to featureKey and userId | Returns a matching user-feature data mapping corresponding to featureKey and userId passed |
| set | data | Store user-feature data mapping | null |
Optional Methods (Settings Storage)
Supported from SDK version
1.35.0onwards
These methods are optional but highly recommended for performance optimization. When implemented, the SDK can load settings from your storage instead of fetching them from VWO servers during initialization.
| Method Name | Params | Description | Returns |
|---|---|---|---|
getSettings | accountId, sdkKey | Retrieves cached VWO settings | This function returns an object that includes the settings and a timestamp indicating when it was stored. |
setSettings | data | Stores VWO settings along with a timestamp | void |
ISettingsData Interface:
interface ISettingsData {
settings: Record<string, any>; // The SDK configuration object
timestamp: number; // Unix timestamp in milliseconds when settings were stored
}Settings Storage Configuration
TTL (Time To Live)
TTL controls how long cached settings remain valid before the SDK fetches fresh settings from VWO servers.
- Type:
number(milliseconds) - Default:
7200000(2 hours) - Minimum:
60000(1 minute) - Location: Set via
protected ttlproperty in your storage connector class
How TTL Works:
- When settings are stored via
setSettings, a timestamp is saved - During SDK initialization,
getSettingsis called - The SDK calculates:
currentTime - storedTimestamp - If the difference exceeds TTL, settings are considered expired
- Expired settings trigger a fresh fetch from VWO servers
Example:
class RedisStorageConnector extends Connector {
protected ttl: number = 3600000; // 1 hour TTL
constructor() {
super();
// TTL can be set in constructor or as a class property
}
}alwaysUseCachedSettings
alwaysUseCachedSettings is a boolean flag that, when enabled, makes the SDK always use cached settings regardless of TTL expiration.
- Type:
boolean - Default:
false - Location: Set via
protected alwaysUseCachedSettingsproperty in your storage connector class
Behavior:
- When
false(default): SDK respects TTL and fetches fresh settings when cache expires - When
true: SDK always uses cached settings, skipping TTL validation entirely
Use Cases:
false: Recommended for most scenarios. Ensures settings stay relatively fresh while benefiting from cachingtrue: Useful when you want maximum performance and control settings updates manually, or when network calls are expensive/restricted
Example:
class RedisStorageConnector extends Connector {
protected ttl: number = 3600000; // 1 hour TTL
constructor() {
super();
// TTL can be set in constructor or as a class property
}
}alwaysUseCachedSettings
alwaysUseCachedSettings is a boolean flag that, when enabled, makes the SDK always use cached settings regardless of TTL expiration.
- Type:
boolean - Default:
false - Location: Set via
protected alwaysUseCachedSettingsproperty in your storage connector class
Behavior:
- When
false(default): SDK respects TTL and fetches fresh settings when cache expires - When
true: SDK always uses cached settings, skipping TTL validation entirely
Use Cases:
false: Recommended for most scenarios. Ensures settings stay relatively fresh while benefiting from cachingtrue: Useful when you want maximum performance and control settings updates manually, or when network calls are expensive/restricted
Example:
class CustomStorageConnector extends Connector {
protected alwaysUseCachedSettings: boolean = true; // Always use cache
constructor() {
super();
}
}Important Notes:
- Settings storage is completely transparent to variation evaluation logic
- If
getSettingsorsetSettingsthrow errors, SDK falls back to fetching from VWO servers - Settings are validated for
accountIdandsdkKeymatch before use - Invalid or mismatched settings trigger a fresh fetch
Updated about 23 hours ago
