On this page

Using Private Attributes

Use private attributes in Statsig SDKs to evaluate feature gates and experiments without sending sensitive user data to Statsig servers.

Evaluating feature gates, dynamic configs, segments, and experiments without logging user data

Private attributes let you evaluate feature gates, dynamic configs, segments, and experiments in Statsig without sending sensitive user data to Statsig's servers. You mark any field used for evaluation as private, and Statsig strips it from the user object before logging. Use them when legal requirements or internal policy prevent you from sending PII to a third party.

How private attributes work

You can make any field used for evaluation private.

Making the userID field private breaks your experience in the Statsig console: the Users tab, metrics charts, event logs, and Pulse metrics won't populate accurately. To hide the user ID, use a stable, one-way hash to preserve the ability to analyze user behavior.

For example, suppose you want to use an email condition:

  1. Create a feature gate with a condition that passes on certain emails or domains
  2. Pass email: email@domain.com in privateAttributes rather than in the top level email field
  3. Test it out in the Test Gate console after saving changes

Private attributes

When evaluating rules and conditions, Statsig checks for fields at the top level, then in custom attributes, and finally in privateAttributes. Not passing email at the top level causes the evaluator to check custom and then privateAttributes before evaluating the condition.

To keep ip and userAgent private while still using browser or IP checks in the console, place them in the privateAttributes dictionary instead of at the top level of the user object. The same applies to country, locale, custom fields, and so on.

The statsig-node SDK illustrates how this works (this is also how Statsig servers evaluate gates): https://github.com/statsig-io/node-js-server-sdk/blob/d1cb9431fb68b40f840254fce70363de1dc51aa5/src/Evaluator.js#L374

Don't provide a privateAttribute key anywhere else in the user object. Statsig drops the entire privateAttributes dictionary, but still logs any duplicate fields at the top level or in the custom object (and evaluates against them).

Client vs server SDKs

Client and single-user environment SDKs send the user object with the initialize call to evaluate the user against every gate in your Statsig project. The SDK sends privateAttributes with this call, but Statsig servers don't store or log them. Statsig servers require the privateAttributes field to evaluate gate, config, and experiment conditions, then strip it from the user object before any logging occurs. Client SDKs remove privateAttributes before logging any events; the SDK uses the field only for gate evaluation.

Example with the @statsig/js-client SDK: https://github.com/statsig-io/js-client-monorepo/blob/17fb70f1bea00d07e156cf6ff03b8024bbc1b197/packages/client-core/src/EventLogger.ts#L325

If client SDK behavior doesn't meet your needs, Statsig server SDKs provide a stronger guarantee: privateAttributes never leave your server. Server SDKs download the definition of each gate, config, and experiment and evaluate them locally.

privateAttributes stripped from event logs with the statsig-node SDK: https://github.com/statsig-io/node-js-server-sdk/blob/d1cb9431fb68b40f840254fce70363de1dc51aa5/src/LogEvent.js#L21

Evaluation happening locally to the server on privateAttributes in the statsig-node SDK: https://github.com/statsig-io/node-js-server-sdk/blob/d1cb9431fb68b40f840254fce70363de1dc51aa5/src/Evaluator.js#L374

All Statsig SDKs are open source and available on GitHub. Review the implementation of privateAttributes in the SDK you're using, or reach out on Slack for guidance.
To ensure that user PII never travels over the network back to Statsig during Client SDK initialization, use Client Bootstrapping. Provide the privateAttributes as part of the user object on the server, in the getClientInitializeResponse(<user object>) call. The getClientInitializeResponse call generates all assignments locally on your server. You then pass these assignments as initializeValues to the client SDK, which eliminates the need to send any user attributes from the client device to Statsig.

Event logging

The SDK strips the privateAttributes field from the user object for any logEvent calls on both client and server SDKs. On server SDKs, you can omit the field from logEvent calls because no evaluation occurs at log time. If you use the same user object throughout, the SDK handles dropping privateAttributes for you.

Was this helpful?