Private attributes
Read time: 10 minutes
Last edited: Mar 16, 2023
Overview
This topic explains how to configure private context and user attributes in LaunchDarkly SDKs. These features are available for both client-side and server-side SDKs.
A context is a generalized way of referring to the people, services, machines, or other resources that encounter feature flags in your product. Contexts replace another data object in LaunchDarkly: "users." To learn more, read Contexts and segments.
Creating contexts and evaluating flags based on them is supported in the latest major versions of most of our SDKs. For these SDKs, the code samples on this page include the two most recent versions.
You can optionally configure your SDK to treat some or all attributes as private context attributes. You can use private context attributes for targeting purposes, but the SDK removes them from the context data it sends back to LaunchDarkly.
The context key is not optional. You cannot set either the context key or the context kind as a private attribute.
If you initially mark an attribute as private, LaunchDarkly will continue to treat the attribute as private in subsequent evaluations as long as the context is in the Contexts list, even if you later remove the "private" designation from the attribute. If you no longer want LaunchDarkly to treat the attribute as private, remove the "private" designation within the SDK, delete the context from the Contexts list, and re-evaluate the context.
Depending on the type of SDK you use, LaunchDarkly does not receive or store the information in private attributes:
- If you are using a server-side SDK, the SDK will not send the private attribute back to LaunchDarkly.
- If you are using a client-side SDK, the SDK will send the private attribute back to LaunchDarkly for evaluation. However, the SDK won't send the attribute to LaunchDarkly in events data, LaunchDarkly won't store the private attribute, and the private attribute will not appear on the Contexts list or on the detail page for the context.
Details about each SDK's configuration are available in the SDK-specific sections below.
Client-side SDKs
Here are the configuration options for private context and user attributes in client-side SDKs.
- .NET (client-side)
- Android
- C/C++ (client-side)
- Electron
- Flutter
- iOS
- JavaScript
- Node.js (client-side)
- React Native
- React Web: The React SDK relies on the JavaScript SDK for context-related functionality.
- Roku
.NET (client-side)
Expand .NET (client-side) code sample
In the client-side .NET SDK there are two ways to define private attributes for the entire LaunchDarkly client:
- When creating the LaunchDarkly
Configuration
object, you can call theAllAttributesPrivate
method, which takes in a boolean parameter. Iftrue
, all context attributes except the kind and key are removed for all contexts before the SDK sends the context to LaunchDarkly. - When creating the LaunchDarkly
Configuration
object, you can call thePrivateAttributes
method, which takes any number of attribute names or slash-delimited paths to designated JSON properties within an attribute, such as/address/street
. If any context has a custom or built-in attribute that matches one of these names, the SDK removes it before sending the context to LaunchDarkly.
You can also mark attributes as private when building the context object by calling Private()
on the context builder.
For example:
var context = Context.Builder("context-key-123abc").Set("email", "sandy@example.com").Private("email").Build();
When the SDK sends this context back to LaunchDarkly, it removes the email
attribute.
Android
Expand Android code sample
In the Android SDK you can define private attributes for the entire LaunchDarkly client. When creating the LDConfig
object, call the privateAttributes
method, which takes in a set of custom or built-in attributes as a parameter. If any context has a custom or built-in attribute named in this set, the SDK removes it before sending the context to LaunchDarkly.
Here's how to configure private attributes:
LDConfig ldConfig = new LDConfig.Builder().events(Components.sendEvents().privateAttributes("name", "group")).build();
You can also mark attributes as private when building the context object by using the private versions of the builder methods to set the attributes. For example:
LDContext context = LDContext.builder("context-key-123abc").set("email", "sandy@example.com").set("name", "Sandy").set("group", "Microsoft").privateAttributes("name", "group")
When the SDK sends this context back to LaunchDarkly, it removes the name
and group
attributes.
C/C++ (client-side)
Expand C/C++ (client-side) code sample
In the C/C++ SDK there are two ways to define private attributes for the LaunchDarkly client:
- When creating the
LDConfig
object, you can set theallAttributesPrivate
value totrue
. When you do this, all user attributes except the key are removed before the SDK sends the user to LaunchDarkly. - When creating the
LDConfig
object, you can configure a map ofprivateAttributeNames
. If any user has a custom or built-in attribute named in this list, the SDK removes it before sending the user to LaunchDarkly.
struct LDConfig *config = LDConfigNew("mobile-key-123abc");// Mark all attributes privateLDConfigSetAllAttributesPrivate(config, true);
Electron
Expand Electron code sample
To mark all user attributes except the key as private, use the allAttributesPrivate
option:
const user = {key: 'user-key-123abc',name: 'Sandy Smith',email: 'sandy@example.com'};const client = LDElectron.initialize('client-side-id-123abc', user, {allAttributesPrivate: true});
In the above example, the SDK removes the name
and email
attributes.
You can also specify an array of which attributes should be private with the privateAttributeNames
option. You can configure this option on a per-user basis by specifying which attributes should be private in your user object.
This option is configured in both the user object and the configuration object:
const user = {key: 'user-key-123abc',name: 'Sandy Smith',email: 'sandy@example.com',privateAttributeNames: ['email']};const client = LDElectron.initialize('client-side-id-123abc', user, {privateAttributeNames: ['email']});
In the above example, the SDK sends only the key
and name
back to LaunchDarkly.
Flutter
Expand Flutter code sample
In the Flutter SDK, you can define private attributes for the entire LaunchDarkly client. When you create the LDConfig
object, you can call the privateAttributeNames
method, which takes in a set of custom or built-in attributes as a parameter. If any user has a custom or built-in attribute named in this set, the SDK removes it before sending the user to LaunchDarkly.
Set<String> privateAttributes ={ 'name' // built-in attribute, 'group' // custom attribute};LDConfig ldConfig = new LDConfigBuilder().privateAttributeNames(privateAttributes).build();
You can also mark attributes as private when building the user object by using the private versions of the builder methods to set the attributes. For example:
LDUser user = LDUserBuilder('user-key-123abc').email('sandy@example.com').privateName('Jane').privateCustom('group', LDValue.ofString('microsoft')).build();
When the SDK sends this user back to LaunchDarkly, the name
and group
attributes are removed.
iOS
Expand iOS code sample
In the iOS SDK there are two ways to define private attributes for the entire LaunchDarkly client:
- When creating the
LDConfig
object, you can set theallContextAttributesPrivate
attribute totrue
. - When creating the LDConfig object, you can set the
privateContextAttributes
property to a list ofReference
s, such as[Reference("name"), Reference("/address/state")]
. If any context has a custom or built-in attribute named in this list, the SDK removes it before sending the context to LaunchDarkly.
You can also mark attributes as private on a particular LDContext
instance, for example:
var contextBuilder = LDContextBuilder(key: "context-key-123abc")contextBuilder.trySetValue("name", .string("Sandy"))contextBuilder.trySetValue("group", .array([LDValue(stringLiteral: "microsoft")]))contextBuilder.addPrivateAttribute(Reference("name"))contextBuilder.addPrivateAttribute(Reference("group"))let context = try contextBuilder.build().get()
JavaScript
Expand JavaScript code sample
To mark all attributes except the key as private in the JavaScript SDK, you can use the allAttributesPrivate
option:
const context = {kind: 'user',key: 'user-key-123abc',name: 'Sandy Smith',email: 'sandy@example.com'};const ldclient = ld.initialize('client-side-id-123abc', context, options = {allAttributesPrivate: true});
In the above example, the name
and email
attributes are removed.
You can configure this option either in the configuration object or in the context object, by specifying an array of attributes that should be private. In the configuration object, specify your array of attributes in the privateAttributes
configuration option. In the context object, specify your array of attributes in the privateNames
field of the reserved _meta
property.
Here's how:
const context = {kind: 'user',key: 'context-key-123abc',name: 'Sandy Smith',email: 'sandy@example.com',_meta: {privateAttributes: ['email']}};const ldclient = ld.initialize('client-side-id-123abc', context, options = {privateAttributes: ['email']});
In the above example, the SDK sends only the context's key and name back to LaunchDarkly.
Node.js (client-side)
Expand Node.js (client-side) code sample
To mark all user attributes except the key as private in the Node.js SDK, you can use the allAttributesPrivate
option:
const context = {kind: 'user',key: 'user-key-123abc',name: 'Sandy Smith',email: 'sandy@example.com'};const client = ld.initialize('client-side-id-123abc', context, {allAttributesPrivate: true});
You can also specify an array of which attributes should be private with the privateAttributes
option. You can configure this option on a per-context basis by specifying which attributes should be private in your context object.
You can configure this option in both the context object and the configuration object:
const context = {kind: 'user',key: 'user-key-123abc',name: 'Sandy Smith',email: 'sandy@example.com'_meta: {privateAttributes: ['email']}};const client = ld.initialize('client-side-id-123abc', context, {privateAttributes: ['email']});
In the above example, the SDK sends only the context key and name back to LaunchDarkly.
React Native
Expand React Native code sample
You can configure this option in the configuration object, to apply to all contexts, either for all attributes or some attributes:
const config = {mobileKey: 'mobile-key-123abc',allAttributesPrivate: true};await ldClient.configure(config, context);
To learn more, read allAttributesPrivate
and privateAttributes
on LDConfig
.
You can also mark an attribute as private for a particular context:
const context = {kind: 'user',key: 'user-key-123abc',firstName: 'Sandy',lastName: 'Smith',email: 'sandy@example.com',address: {street: '123 Main St',city: 'Springfield'},_meta: {privateAttributes: ['email', '/address/street']}};
For attributes that are objects, you can mark specific fields private, using the /
delimiter followed by the attribute name, then the /
delimiter followed by the JSON property within the value. In the example, the attribute "address": { "street": "Main St", "city": "Springfield" }
has only the /address/street
marked as private.
React Web
All context-related functionality provided by the JavaScript SDK is also available in the React SDK.
Roku
Expand Roku code sample
To mark specific attributes as private:
user.addPrivateAttribute(String)
Server-side SDKs
Here are the configuration options for private context and user attributes in server-side SDKs:
- .NET (server-side)
- Apex
- C/C++ (server-side)
- Erlang
- Go
- Haskell
- Java
- Lua
- Node.js (server-side)
- PHP
- Python
- Ruby
- Rust
.NET (server-side)
Expand .NET (server-side) code sample
In the server-side .NET SDK there are two ways to define private attributes for the entire LaunchDarkly client:
- When creating the LaunchDarkly
Configuration
object, you can configureEvents
withAllAttributesPrivate
, which takes in a boolean parameter. Iftrue
, the SDK removes all attributes for all contexts before sending the context to LaunchDarkly, except the key. - Or, you can configure
Events
withPrivateAttributes
, which takes any number of attribute names or slash-delimited paths to designated a JSON property within an attribute, such as/address/street
. If any context has a custom or built-in attribute that matches one of these names, the SDK removes it before sending the context to LaunchDarkly.
You can also mark attributes as private when building the context object by calling Private()
after setting the attribute on the context builder.
For example:
var context = Context.Builder("context-key-123abc").Set("email", "sandy@example.com").Private("email").Build();
When the SDK sends this context back to LaunchDarkly, it removes the email
attribute.
Apex
Expand Apex code sample
Optionally, you can configure the Apex SDK to treat some or all user attributes as private user attributes. You can use private user attributes for targeting, but they are redacted from the user data sent back to LaunchDarkly.
In the Apex SDK there are two ways to define private attributes for the LaunchDarkly client:
When creating the
LDConfig
object, you can usesetAllAttributesPrivate(true)
. When you do this, all user attributes, except the key, are redacted before the SDK sends the user to LaunchDarkly.Here's how:
LDConfig config = new LDConfig.Builder().setAllAttributesPrivate(true).build();You can also define private attribute names on a per-user basis.
Here's how:
Set<String> privateAttributes = new Set<String>();privateAttributes.add('firstName');LDUser user = new LDUser.Builder('user-key-123abc').setFirstName('alice').setPrivateAttributeNames(privateAttributes).build();
C/C++ (server-side)
Expand C/C++ (server-side) code sample
In the C/C++ SDK there are three ways to define private attributes for the LaunchDarkly client:
When creating the
LDConfig
object, you can useLDConfigSetAllAttributesPrivate
. When you do this, all user attributes (except the key) for the user are removed before the SDK sends the user to LaunchDarkly.For example:
LDConfigSetAllAttributesPrivate(config, true);When creating the
LDConfig
object, you can list specific private attributes withLDConfigAddPrivateAttribute
. If any user has a custom or built-in attribute named in this list, the SDK removes it before sending the user to LaunchDarkly.Here's how:
LDConfigAddPrivateAttribute(config, "email");You can also define private attribute names on a per-user basis. For example:
LDUserAddPrivateAttribute(user, "email");
Erlang
Expand Erlang code sample
Here's how to set context attributes as private for all contexts:
ldclient:start_instance("sdk-key-123abc", your_instance, #{private_attributes => [email]})
Here's how to set context attributes as private for a specific context:
ContextWithPrivateAttributes = ldclient_context:set_private_attributes([<<"name">>, <<"/address/street">>],ldclient_context:set(<<"name">>, <<"Global Health Services">>,ldclient_context:set(<<"email">>, <<"info@globalhealthexample.com">>,ldclient_context:set(<<"address">>, #{<<"street">> => <<"123 Main Street">>,<<"city">> => <<"Springfield">>},ldclient_context:new(<<"context-key-456def">>, <<"organization">>))))),
In the example, only the name
and /address/street
attributes are private for this context.
Go
Expand Go code sample
In the Go SDK there are two ways to define private attributes for the entire LaunchDarkly client:
- You can set the configuration option
AllAttributesPrivate
to true. If you enable this, the SDK removes all attributes for all contexts before it sends the context to LaunchDarkly, except the key and kind. - You can set the configuration option
PrivateAttributes
to a list of attribute names. If any context has an attribute named in this list, the SDK removes it before sending the context to LaunchDarkly.
Here's how to to define private attributes:
import (ld "github.com/launchdarkly/go-server-sdk/v6""github.com/launchdarkly/go-server-sdk/v6/ldcomponents")var config ld.Config// Make all attributes private for all contextsconfig.Events = ldcomponents.SendEvents().AllAttributesPrivate(true)// Or, make just the email and address attributes private for all contextsconfig.Events = ldcomponents.SendEvents().PrivateAttributes("name", "email")
You can also define a set of private attributes on the context object itself. In the following example, "email" and the "street" field of the "address" attribute are private for this context, in addition to any private attributes that were specified globally:
import ("github.com/launchdarkly/go-sdk-common/v3/ldcontext")context := ldcontext.NewBuilder("context-key-123abc").Kind("organization").Name("Global Health Services").SetString("email", "info@globalhealthexample.com").SetValue("address", ldvalue.ObjectBuild().SetString("street", "123 Main Street").SetString("city", "Springfield")).Private("email").Private("/address/street").Build()
Haskell
Expand Haskell code sample
Optionally, you can configure the Haskell SDK to treat some or all context attributes as private attributes. You can use private context attributes for targeting purposes, but the SDK removes private context attributes from the data it sends to LaunchDarkly.
When you create the Config
object, use configSetAllAttributesPrivate
to set all context attributes as private. When you do this, all context attributes, except the key and kind, are removed before the SDK sends the context to LaunchDarkly.
Here's how:
makeConfig "sdk-key" & configSetAllAttributesPrivate True
When you create the Config
object, you can list specific private attributes with configSetPrivateAttributeNames
. If any context has attributes named in this list, the SDK removes them before sending the context to LaunchDarkly.
Here's an example:
import qualified Data.Set as Simport qualified LaunchDarkly.Server.Reference as RmakeConfig sdkKey& configSetAllAttributesPrivate True& configSetPrivateAttributeNames (S.fromList $ map R.makeLiteral ["name", "email"])
You can also define private attribute names on a per-context basis.
For example:
makeContext "key" "user"& withName "Sandy"& withAttribute "email" "sandy@example.com"& withPrivateAttributes (S.fromList $ map R.makeLiteral ["name", "email"])
Java
Expand Java code sample
In the Java SDK there are two ways to define private attributes for the entire LaunchDarkly client:
- When creating the
LDConfig
object, you can call theallAttributesPrivate
method, which takes in a boolean parameter. Iftrue
, all context attributes except the key for all contexts are removed before the SDK sends the context to LaunchDarkly. - When creating the
LDConfig
object, you can call theprivateAttributes
method, which takes in a set of custom or built-in attributes as a parameter. If any context has a custom or built-in attribute named in this list, the SDK removes it before sending the context to LaunchDarkly.
Here's how to define private attributes:
LDConfig configWithAllAttributesPrivate = new LDConfig.Builder().events(Components.sendEvents().allAttributesPrivate(true)).build();LDConfig configWithSpecificAttributesPrivate = new LDConfig.Builder().events(Components.sendEvents().privateAttributes("name", "email", "someAttribute")).build();
You can also mark attributes as private when building the context object by calling the privateAttributes
builder method. For example:
LDContext context = LDContext.builder("context-key-123abc").set("email", "sandy@example.com").privateAttributes("email").build();
When the SDK sends this context back to LaunchDarkly, it removes the email
attribute.
Lua
Expand Lua code sample
Here's how to mark all attributes as private:
local user = ld.makeUser({allAttributesPrivate = true,key = "user-key-123abc",firstName = "Sandy",lastName = "Smith",email = "sandy@example.com",custom = {groups = { "Google", "Microsoft" }}})
Here's how to mark only some attributes as private:
local user = ld.makeUser({key = "user-key-123abc",firstName = "Sandy",lastName = "Smith",email = "sandy@example.com",custom = {groups = { "Google", "Microsoft" }}privateAttributeNames = { "email" }})
When the SDK sends this user back to LaunchDarkly, it removes the email
attribute.
Node.js (server-side)
Expand Node.js (server-side) code sample
In the Node.js SDK there are two ways to define private attributes for the entire LaunchDarkly client:
- In the LaunchDarkly
LDOptions
, you can setallAttributesPrivate
totrue
. If you enable this, the SDK removes all attributes for all contexts before sending the context to LaunchDarkly, except the kind and key. - In the LaunchDarkly
LDOptions
object, you can define a list ofprivateAttributes
. If any context has a custom or built-in attribute named in this list, the SDK removes it before sending the context to LaunchDarkly.
You can also define a set of privateAttributes
on the context object. For example:
const context = {kind: 'user',key: 'user-key-123abc',email: 'sandy@example.com',_meta: {privateAttributes: ['email'],}};
When the SDK sends this context back to LaunchDarkly, it removes the email
attribute.
PHP
Expand PHP code sample
In the PHP SDK there are two ways to define private attributes for the entire LaunchDarkly client:
- In the LaunchDarkly
config
, you can setall_attributes_private
totrue
. If you enable this, the SDK removes all attributes except the key and kind from a context before sending the context to LaunchDarkly. - In the LaunchDarkly
config
object, you can define a list ofprivate_attribute_names
. If any context has a custom or built-in attribute named in this list, the SDK removes it before sending the context to LaunchDarkly.
You can also mark attributes as private when building the context object by calling the equivalent "private" LDContextBuilder
method.
For example:
$context = LDContext::builder('context-key-123abc')->set('email', 'sandy@example.com')->private('email')->build();
When the SDK sends this context back to LaunchDarkly, it removes the email
attribute.
Python
Expand Python code sample
In the Python SDK there are two ways to define private attributes for the LaunchDarkly client:
- In the LaunchDarkly
config
, you can setall_attributes_private
to true. If you enable this, the SDK removes all context attributes for all contexts before sending the context to LaunchDarkly, except the key. - In the LaunchDarkly
config
object, you can define a list of attributes inprivate_attributes
. If any context has a custom or built-in attribute named in this list, the SDK removes it before sending the context to LaunchDarkly.
You can also mark attributes as private when building the context object by calling the private
builder method. For example:
context = Context.builder("context-key-123abc") \.set("email", "sandy@example.com") \.private("email") \.build()
When the SDK sends this context back to LaunchDarkly, it removes the email
attribute.
Ruby
Expand Ruby code sample
In the Ruby SDK there are two ways to define private attributes for the entire LaunchDarkly client:
- In the LaunchDarkly
config
, you can setall_attributes_private
to true. If you enable this, the SDK removes all context attributes for all contexts before sending the context to LaunchDarkly, except the key. - In the LaunchDarkly config object, you can define a list of
private_attributes
. If any context has a custom or built-in attribute named in this list, the SDK removes it before sending the context to LaunchDarkly.
You can also define a set of privateAttributes
on the context object. For example:
context = LaunchDarkly::LDContext.create({key: "user-key-123abc",kind: "user",firstName: "Sandy",lastName: "Smith",email: "sandy@example.com",groups: ["Google", "Microsoft"],_meta: {privateAttributes: ['email']}})
When the SDK sends this context back to LaunchDarkly, it removes the email
attribute.
Rust
Expand Rust code sample
In the Rust SDK there are two ways to define private attributes for the entire LaunchDarkly client:
- In the LaunchDarkly config object, you can set
all_attributes_private
to true. If you enable this, the SDK removes all attributes for all contexts before sending the context to LaunchDarkly, except the key and kind. - In the LaunchDarkly config object, you can define a list of
private_attributes
. If any contexts has an attribute named in this list, the SDK removes it before sending the context to LaunchDarkly.
You can also define private attributes on the context object. For example:
let context = ContextBuilder::new("context-key-123abc").set_value("email", "youremail@example.com".into()).add_private_attribute(Reference::new("email")).build()?;
When the SDK sends this context back to LaunchDarkly, it removes the email
attribute.