Javascript SDK Usage
Waiting for Features
You can wait on the features to be loaded from our servers by using .onClientInitialized()
function. It returns a promise that you can use to wait until features are ready to be used:
devcycleClient.onClientInitialized().then(() => {
if (devcycleClient.variableValue('<YOUR_VARIABLE_KEY>', false)) {
...
} else {
...
}
})
You can also pass in a callback which will get called after the features are loaded:
devcycleClient.onClientInitialized((err) => {
if (err) {
// error state
}
if (devcycleClient.variableValue('<YOUR_VARIABLE_KEY>', false)) {
...
} else {
...
}
})
Using Variable Values
To get values from your Variables, variableValue()
is used to fetch Variable values using the identifier key
coupled with a default value.
The default value can be of type String
, Boolean
, Number
, or Object
.
const variable = devcycleClient.variableValue(
'<YOUR_VARIABLE_KEY>',
'default value',
)
If you would like to get the full Variable
object using the variable()
method it also contains the following params:
key
: the key identifier for the Variabletype
: the type of the Variable, one of:String
/Boolean
/Number
/JSON
value
: the Variable's valuedefaultValue
: the Variable's default valueisDefaulted
: if the Variable is using thedefaultValue
evalReason
: evaluation reason for why the variable was bucketed into its value
The DVCVariable
type interface can be found here.
If the value is not ready, it will return the default value used in the creation of the variable.
Variable Updates
The onUpdate
param on a Variable
Object accepts a handler function that will be called whenever a variable value has changed.
This can occur as a result of a project configuration change or calls to identifyUser()
or resetUser()
.
To learn more, visit our Realtime Updates page.
There can only be one onUpdate function registered at a time. Subsequent calls to this method will overwrite the previous handler:
const variable = devcycleClient.variable('<YOUR_VARIABLE_KEY>', 'default value')
variable.onUpdate((value) => {
// value returned when the value of the variable changes
})
Identifying User
To identify a different user, or the same user passed into the initialize function with more attributes, pass in the entire user attribute object into identifyUser
:
const user = {
user_id: 'user1',
name: 'user 1 name',
customData: {
customKey: 'customValue',
},
}
devcycleClient.identifyUser(user)
To wait on Variables that will be returned from the identify call, you can pass in a callback or use the Promise returned if no callback is passed in:
const variableSet = await devcycleClient.identifyUser(user)
// OR
devcycleClient.identifyUser(user, (err, variables) => {
// variables is the variable set for the identified user
})
Reset User
To reset the user into an anonymous user, resetUser
will reset to the anonymous user created before or will create one with an anonymous user_id
.
devcycleClient.resetUser()
To wait on the Features of the anonymous user, you can pass in a callback or use the Promise returned if no callback is passed in:
const variableSet = await client.resetUser()
// OR
devcycleClient.resetUser((err, variables) => {
// variables is the variable set for the anonymous user
})
Get All Features
To retrieve all the Features returned in the config:
const features = devcycleClient.allFeatures()
If the SDK has not finished initializing, these methods will return an empty object. Read Waiting for Features to mitigate this.
See getFeatures in the Bucketing API for detailed response formats.
Get All Variables
To grab all the Features returned in the config:
const variables = devcycleClient.allVariables()
If the SDK has not finished initializing, these methods will return an empty object. Read Waiting for Features to mitigate this.
See getVariables in the Bucketing API for detailed response formats.
This method is intended to be used for debugging and analytics purposes, not as a method for retrieving the value of Variables to change code behaviour. For that purpose, we strongly recommend using the individual variable access method described in Using Variable Values Using this method instead will result in no evaluation events being tracked for individual variables, and will not allow the use of other DevCycle features such as Code Usage detection
Tracking Events
To track events, pass in an object with at least a type
key:
const event = {
type: 'my_event_type', // this is required
date: new Date(),
target: 'my_target',
value: 5,
metaData: {
key: 'value',
},
}
devcycleClient.track(event)
The SDK will flush events every 10s or flushEventsMS
specified in the options. To manually flush events, call:
await devcycleClient.flushEvents()
// or
devcycleClient.flushEvents(() => {
// called back after flushed events
})
Subscribing to SDK Events
The SDK can emit certain events when specific actions occur which can be listened on by subscribing to them:
devcycleClient.subscribe(
'variableUpdated:*',
(key: string, variable: DVCVariable | null) => {
// key is the variable that has been updated
// The new value can be accessed from the variable object passed in: variable?.value
// The variable argument will be null if the variable is no longer being served a value
console.log(`New variable value for variable ${key}: ${variable?.value}`)
},
)
The first argument is the name of the event that you can subscribe to. The subscribe
method will throw an error if you try to
subscribe to an event that doesn't exist. These are the events you can subscribe to:
Event | Key | Handler Params | Description |
---|---|---|---|
Initialized | initialized | (initialized: boolean) | An initialized event is emitted once the SDK has received its first config from DevCycle. This event will only be emitted once. |
Error | error | (error: Error) | If any error occurs in the SDK, this event emits that error. |
Variable Updated | variableUpdated:* | (key: string, variable: DVCVariable | null) | This event gets triggered when a variable value changes for a user. You can subscribe to all variable updates using the * identifier, or you can pass in the key of the variable you want to subscribe to, e.g. variableUpdated:my_variable_key . |
Variable Evaluated | variableEvaluated:* | (key: string, variable: DVCVariable) | This event gets triggered when a variable is evaluated. You can subscribe to all variable evaluations using the * identifier, or you can pass in the key of the variable evaluation you want to subscribe to, e.g. variableEvaluated:my_variable_key . |
Feature Updated | featureUpdated:* | (key: string, feature: DVCFeature | null) | This event gets triggered when a feature's variation changes for a user. You can subscribe to all feature updates using the * identifier, or you can pass in the key of the feature you want to subscribe to, e.g. featureUpdated:my_feature_key . |
Config Updated | configUpdated | This event gets triggered when there are any variable, variation, or feature changes. |
Bootstrapping and Server-Side Rendering
If you are using Next.js, we recommend using the Next.js SDK instead of this option.
The SDK supports the ability to have its configuration bootstrapped during initialization, which allows it to start serving up-to-date Variable values immediately. Using this option skips the initial configuration fetch that normally occurs when the page is first loaded, reducing the time before correct content can be shown.
This is especially useful for server-side rendering use-cases, where you may have a configuration already on the server which can be provided in the page response.
To provide a bootstrapped config, pass the option when initializing the SDK:
const user = { user_id: 'my_user' }
const devcycleClient = initializeDevCycle(
'<DEVCYCLE_CLIENT_SDK_KEY>',
user,
{
bootstrapConfig: CONFIG_DATA
},
)
If you are using a Javascript-based server rendering framework like Remix, the DevCycle Node.js SDK provides a convenient way to obtain the configuration data needed for bootstrapping. See the Node.js documentation for more information.
EdgeDB
EdgeDB allows you to save user data to our EdgeDB storage so that you don't have to pass in all the user data every time you identify a user.
To get started, contact us at support@devcycle.com to enable EdgeDB for your project.
Once you have EdgeDB enabled in your project, pass in the enableEdgeDB
option to turn on EdgeDB mode for the SDK:
const user = {
user_id: 'my_user',
customData: {
amountSpent: 50,
},
}
const options = {
enableEdgeDB: true,
}
const devcycleClient = initializeDevCycle(
'<DEVCYCLE_CLIENT_SDK_KEY>',
user,
options,
)
This will send a request to our EdgeDB API to save the custom data under the user my_user
.
In the example, amountSpent
is associated to the user my_user
. In your next identify
call for the same user_id
,
you may omit any of the data you've sent already as it will be pulled from the EdgeDB storage when segmenting to experiments and features:
devcycleClient.identifyUser({ user_id: 'my_user' }) // no need to pass in "amountSpent" any more!