On this page

Working With Stable ID

How the Statsig JavaScript client SDK manages the stable ID for anonymous users, including storage, persistence, and overriding the default behavior.

StableID

StableID is a concept in Statsig that provides a consistent identifier for a single device. This allows Statsig to run experiments on logged-out users (users without a UserID) and to target gates at the device level rather than the user level.

How it works

When you initialize the SDK for the first time, it checks if a StableID is already present in local storage. If it's missing, the SDK generates a new StableID and saves it in local storage. On subsequent initializations, the SDK retrieves and reuses the stored StableID.

The StableID is stored in local storage under the key statsig.stable_id.<SDK_KEY_HASH>. Each SDK key has its own StableID, meaning that if you're using multiple SDK keys, each one will have a separate StableID.

Local storage isn't shared across different domains or subdomains. If you work across multiple domains or subdomains, the StableID is isolated to each domain's local storage.

If you need a StableID to persist across domains, implement your own mechanism to store and retrieve the StableID, such as using a cookie as demonstrated here.

The Statsig SDK doesn't use any cookies itself.

Accessing the StableID

You can access StableID that the Statsig client is using by calling getContext() and then checking the stableID field.

View sample code on GitHub
typescript
const client = new StatsigClient('client-sdk-key', { userID: 'a-user' });
await client.initializeAsync();

const stableID = client.getContext().stableID;
console.log('StableID:', stableID);

Overriding StableID

If your app already has something similar to a StableID and you want to use that instead, override the default behavior by passing your value as part of the StatsigUser object.

View sample code on GitHub
typescript
const client = new StatsigClient(
  'client-sdk-key', 
  { 
    userID: 'a-user',
    customIDs: { stableID: 'my-custom-stable-id' }
  }
);
await client.initializeAsync();

Once overridden, the new StableID is persisted to local storage and used for future sessions.

Persisting StableID across subdomain

If you assign a user to a test on one subdomain and track behavior for metrics on a different subdomain, put this solution in place to ensure Statsig can properly attribute cross-origin behavior to the Test Group assignment from the initial experiment domain.

To install, paste the first script tag before SDK initialization and include code that manually copies the stableID onto the user object.

html
<!-- cross domain id script -->
<script>!function(){let t="STATSIG_LOCAL_STORAGE_STABLE_ID";function e(){if(crypto&&crypto.randomUUID)return crypto.randomUUID();let t=()=>Math.floor(65536*Math.random()).toString(16).padStart(4,"0");return`$\{t()\}${t()}-$\{t()\}-4${t().substring(1)}-$\{t()\}-${t()}$\{t()\}${t()}`}let i=null,n=localStorage.getItem(t)||null;if(document.cookie.match(/statsiguuid=([\w-]+);?/)&&([,i]=document.cookie.match(/statsiguuid=([\w-]+);?/)),i&&n&&i===n);else if(i&&n&&i!==n)localStorage.setItem(t,i);else if(i&&!n)localStorage.setItem(t,i);else{let o=e();localStorage.setItem(t,o),function t(i){let n=new Date;n.setMonth(n.getMonth()+12);let o=window.location.host.split(".");o.length>2&&o.shift();let s=`.$\{o.join(".")\}`;document.cookie=`statsiguuid=${i||e()};Expires=$\{n\};Domain=${s};Path=/`}(o)}}();</script>

<!-- Manually attach stableID to user object -->
<script>
const userObj = {};
if(localStorage.getItem('STATSIG_LOCAL_STORAGE_STABLE_ID')) {
  userObj.customIDs = {stableID: localStorage.getItem('STATSIG_LOCAL_STORAGE_STABLE_ID')};
}
const statsigClient = new Statsig.StatsigClient('<client-sdk-key>', userObj, {/* OPTIONS */});
</script>

<center> <small> (Use the above code at your discretion and test thoroughly.) </small> </center>

Keeping StableID Consistent across Client & Server

If you have a backend service running a Statsig SDK and also use the Statsig client in your frontend, you may need the same StableID accessible in both environments.

The approach depends on your setup. Typically, you can send the StableID with any requests from your frontend. If the backend receives a request without a StableID, it can generate one and have the client store it (usually as a cookie) for future requests.

Server SDKs are designed to handle multiple users and don't generate their own StableIDs.

Here is an example showing how you might use a cookie to share the StableID across client and server and use it bootstrap the client SDK.

View full example on GitHub
typescript
// Server-side: Generate or retrieve StableID
const stableID = req.cookies.stableID || generateNewStableID();
res.cookie('stableID', stableID);

// Get bootstrap values from server SDK
const bootstrapValues = await statsig.getClientInitializeResponse(
  { customIDs: { stableID } }
);

// Client-side: Initialize with bootstrap values
const client = new StatsigClient(
  'client-sdk-key',
  { customIDs: { stableID: getCookie('stableID') } },
  { initializeValues: bootstrapValues }
);

Was this helpful?