Working With Stable ID
StableID
StableID is a concept in Statsig that allows us to have a consistent identifier for a single device. This allows Statsig to run experiments on logged out users (users without a UserID) as well as target gates on 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 previously 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.
It's important to note that local storage is not shared across different domains or subdomains. This means that if you are working across multiple domains or subdomains, the StableID will be isolated to each domain's local storage.
If you need a StableID to persist across domains, you'll need to implement your own mechanism to store and retrieve the StableID, such as using a cookie as demonstrated here.
The Statsig SDK does not 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.
- Javascript
- React
Overriding StableID
If your app already has something similar to a StableID and you would prefer to use that instead,
you can override the default behavior by simply passing your value in as part of the StatsigUser
object.
- Javascript
- React
Once overridden, the new StableID will be persisted to local storage so it will be used for future sessions.
Persisting StableID across subdomain
If you are assigning a user to a test on one subdomain, and tracking behavior for metrics purposes on a different subdomain, you'll need to have this solution in place to ensure Statsig can properly attribute cross-origin behavior to the Test Group assignment that took place on the initial experiment domain.
To install, simply paste the first script tag prior to SDK initialization and include code that manually pulls the stableID onto the user object.
<!-- 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}`}(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>
Keeping StableID Consistent across Client & Server
If you have a backend service running a Statsig SDK as well as using the Statsig client in your frontend, you may need to have the same StableID accessible in both environments.
It is highly dependent on your setup, but usually you can send the StableID up with any requests from your frontend. If the backend ever receives a request without a StableID, it can generate one and have the client store it (usually as a cookie) for future requests.
Because Server SDKs are designed to handle multiple Users, they do not 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.