Browser SDKs

Javascript

Javascript browser SDK
Javascript SDK

Introduction

The Javascript browser SDK is intended to be used by web applications running on modern web browsers. All modern web browsers on popular platforms should be supported.

Browser SDKs are tested on the latest versions of Chrome, Firefox, Safari, and Edge.

Telemetry collection within browser SDKs uses Web Workers to aggregate and send telemetry data. If the SDK runs on older browsers without Web Workers support, config evaluation will continue to work but no telemetry data will be collected for that session.

Installation

The SDK can be installed from NPM: https://www.npmjs.com/package/@configdirector/client-sdk

npm install --save @configdirector/client-sdk

Configure and initialize the client

  1. Create an instance of the client providing your client SDK key. You can retrieve a client SDK key under your project settings in the Environments & SDK Keys tab.
  2. Initialize the client to initiate its connection lifecycle.
config-director-setup.ts (Initialize the client)
import { createClient } from "@configdirector/client-sdk";

export const client = createClient("YOUR-CLIENT-SDK-KEY");
await client.initialize();
Before the client is initialized, config values will evaluate to the default value provided in code.

Additional configuration options

metadata

The metadata option allows you to provide your application's name and version. These values can be used in targeting rules conditionals. For example, if a certain feature should only be enabled starting with a certain version of your application.

config-director-setup.ts
import { createClient } from "@configdirector/client-sdk";

export const client = createClient("YOUR-CLIENT-SDK-KEY", {
  metadata: {
    appName: "YOUR-APP-NAME",
    appVersion: "1.0.2",
  },
});

await client.initialize();

logger

By default, the SDK logs to the console and it is set to log warnings and errors only. You can configure a logger by either creating a ConfigDirector console logger with a different log level, or by implementing the ConfigDirectorLogger interface to provide your own logger. The interface can be used to create an adapter to another logging library.

Configure the ConfigDirector console logger to a different level:

config-director-setup.ts
import { createClient, createConsoleLogger } from "@configdirector/client-sdk";

export const client = createClient("YOUR-CLIENT-SDK-KEY", {
  logger: createConsoleLogger("debug"),
});

await client.initialize();

Implement your own logger adapter:

config-director-setup.ts
import { createClient, ConfigDirectorLogger } from "@configdirector/client-sdk";

const myLogger: ConfigDirectorLogger = {
  debug: function (message: string, ...args: any): void {
    // your specific logging library implementation here
  },
  info: function (message: string, ...args: any): void {
    // your specific logging library implementation here
  },
  warn: function (message: string, ...args: any): void {
    // your specific logging library implementation here
  },
  error: function (message: string, ...args: any): void {
    // your specific logging library implementation here
  },
};

export const client = createClient("YOUR-CLIENT-SDK-KEY", {
  logger: myLogger,
});

await client.initialize();

connection

The connection object accepts three optional values:

  • mode
    • The connection mode, which can be either streaming or polling. It is recommended to use the default of streaming unless you have a specific need to use polling instead.
    • Defaults to streaming
  • timeout
    • The timeout, in milliseconds, to be used in initialization and when updating the context. This is how long the initialize method will wait for data from ConfigDirector services before resolving its Promise. If the timeout is reached, initialize will return but the client will still be in an unready status and returning default values. The client will continue to attempt to connect and retrieve config values in the background.
    • If your application is used in environments where the users frequently have poor or no connection, you may want to use a lower timeout, or simply don't await the initialize method call
    • Defaults to 3000 milliseconds
  • url
    • The base URL used to connect to ConfigDirector services
    • This should only be provided if your environment requires you to configure a proxy server in order to connect to ConfigDirector services
config-director-setup.ts
import { createClient } from "@configdirector/client-sdk";

export const client = createClient("YOUR-CLIENT-SDK-KEY", {
  connection: {
    mode: "streaming",
    timeout: 2_000, // 2,000 milliseconds initialization timeout
  },
});

await client.initialize();

Retrieve config values

To synchronously retrieve config values, use the client's getValue method. It requires two arguments. The first argument is the config key, and the second is the default value to be returned if the client has not yet received config values from ConfigDirector services.

You can also subscribe to config value changes via the watch method. It requires three arguments, the config key, the default value, and a callback function to be called when the config value is updated. The watch method itself returns a function to remove that specific listener. Alternatively, you may also call the unwatch method to remove all listeners for a specific config key.

main.ts (Use the client)
import { client } from "./config-director-setup"

// Retrieve the current value
const value = client.getValue("my-config-key", false);

// Subscribe to value updates
const unwatchMyKey = client.watch(
  "my-config-key",
  false,
  (newValue) => {
    console.log("Value updated:", newValue)
  },
);

unwatchMyKey(); // Call the unwatch function returned to remove the listener

client.unwatch("my-config-key"); // Removes all listeners for that key

Both, getValue and watch accept default values for any type supported by that specific config (boolean, string, number, enums). If there is a type mismatch at runtime, the SDK will attempt to cast to the return value. If the cast fails, it will return the value as a string. Mismatched types at runtime are captured by the telemetry collector and will surface as warnings in the ConfigDirector dashboard.

main.ts
client.getValue("my-string-config-key", "Default");

client.getValue("my-integer-config-key", 100);

client.getValue("my-boolean-config-key", false);

client.getValue<MyEnum>("my-enum-config-key", MyEnum.SomeDefaultValue);

Update the user context

A user context can be provided when initializing the client:

config-director-setup.ts
import { createClient } from "@configdirector/client-sdk";

export const client = createClient("YOUR-CLIENT-SDK-KEY");
await client.initialize({
  id: "12345",
  name: "Example User",
  traits: {
    region: "North America", // Any arbitrary traits which can be referenced in targeting rules
  }
});

The user context can also be updated via updateContext:

main.ts
import { client } from "./config-director-setup"

await client.updateContext({
  id: "654321",
  name: "Another User",
  traits: {
    region: "Australia",
  },
});

// Update it to `undefined` (anonymous user context) when a user signs out
await client.updateContext();
In client SDKs (browser and mobile), updating the user context re-establishes a new connection to ConfigDirector servers with the new context. While the new connection is in flight, config values will continue to evaluate to the currently cached values from the prior user context.
Awaiting updateContext will wait until the new config values are downloaded or the connection times out. In the case of a timeout, the client will continue to attempt to connect with the new context in the background.

Other useful client features

The client provides additional properties and methods.

context

Returns the current user context (which may be undefined). When calling updateContext, the context is not immediately updated. The context is updated after the new connection for the new context succeeds (or times out and goes on retry).

isReady

Returns a boolean indicating if the client has been successfully initialized and is ready to evaluate configs for the given user context. It is initially false and becomes true after initialize succeeds. Upon calling updateContext it becomes false again and it is set to true once updateContext succeeds.

unwatchAll

Removes all listeners for all config keys that were previously created via watch.

dispose

Removes all listeners and observers, and closes all connections to ConfigDirector services. Only call dispose when your application shuts down and it will no longer make use of the client instance.

It is generally not needed for applications to call dispose explicitly.

Copyright © 2026