Flags in your code
Read flags and payloads in the browser and on the server, record exposures for experiments and override values while testing.
Every flag gives your code one of these values:
| Value | Meaning |
|---|---|
true / false | Boolean flag: on or off for this user. |
"control", "test", … | Multivariate flag or experiment: the variant. |
undefined | Unknown flag, the flag is off, or flags haven't loaded yet. Show the default. |
Browser
const variant = datahop.getFeatureFlag('new-checkout')
if (variant === 'test') renderNewCheckout()
else renderOldCheckout() // 'control', false or undefinedFlags load when the page starts, and again after identify, group and reset, so targeting by plan or company applies right away. Returning visitors get the previous values instantly while fresh ones load. On a first visit, flags are undefined for a moment. To render only once they're in:
const unsubscribe = datahop.onFeatureFlags((flags) => {
setShowBanner(flags['annual-discount-banner'] === 'test')
})In React, call it in an effect and return unsubscribe as the cleanup. After you change a person's properties, call datahop.reloadFeatureFlags() to pick up flags that depend on them.
| Method | Returns | Counts as exposure |
|---|---|---|
getFeatureFlag(key) | The value | Yes |
isFeatureEnabled(key) | true for on or any variant | Yes |
getFeatureFlagPayload(key) | The payload for the user's value | No |
getAllFlags() | Every flag | No |
Pass { sendEvent: false } to getFeatureFlag or isFeatureEnabled to read a flag without recording an exposure.
Server (Node / Bun)
const variant = await datahop.getFeatureFlag({
distinctId: user.id,
key: 'new-pricing-page',
groups: { company: user.orgId }, // needed for flags that match by company
personProperties: { plan: 'pro' }, // values you know but haven't sent yet
})Reading several flags for the same user in one request costs one network call. If Datahop can't be reached within a few seconds, you get undefined, so always handle the default.
Exposures and experiments
Reading a flag with getFeatureFlag or isFeatureEnabled records that the user saw it. Experiments only count people who were exposed. So:
- Read the flag where the experience starts, such as on the pricing page and not on app start. Otherwise people who never reached the feature dilute the result.
- Handle every variant and
undefined. Showcontrolwhen in doubt. - Logging in doesn't reshuffle anyone. A visitor who saw
testbefore signing up still seestestafter.
Once flags are loaded, the browser SDK also adds the user's flag values to every event. That lets you break down any insight by a flag, such as orders by $feature/new-checkout, without running an experiment.
Override flags while testing
Force values in your own browser for QA, demos or reproducing a bug:
datahop.overrideFeatureFlags({ 'new-checkout': 'test', 'dark-mode': true })
datahop.overrideFeatureFlags(false) // clearOverrides stay until you clear them. They aren't recorded as exposures, so testing in your own browser never skews an experiment.
Other languages
POST /i/flags returns every flag for a user. See the SDK reference. If you use a value in an experiment, also send a $feature_flag_called event so the exposure counts.