# Using Private Attributes

## 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.

{% callout type="warning" %}
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.
{% /callout %}

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

{% figure %}
![Private attributes](https://docs.statsig.com/images/conditions/private-attributes.png)
{% /figure %}

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

{% callout type="warning" %}
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).
{% /callout %}

## 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](https://github.com/statsig-io). Review the implementation of `privateAttributes` in the SDK you're using, or reach out on [Slack](https://www.statsig.com/slack) for guidance.

{% callout type="info" %}
To ensure that user PII never travels over the network back to Statsig during Client SDK initialization, use [Client Bootstrapping](https://docs.statsig.com/client/concepts/initialize#bootstrapping-overview). 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.
{% /callout %}

## 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.
