@betterment-oss/test-track

中文文档
5.0.0发布于 2026/08/25MITTypeScriptES Module近 30 天下载 3934

Javascript Client for Test Track

原始使用文档
文档目录13 节
  1. Installation
  2. Setup
  3. load(options)
  4. create(options)
  5. API
  6. Advanced Configuration
  7. Testing
  8. TypeScript
  9. Vite Plugin
  10. Using TestTrack without a build tool
  11. How to Contribute
  12. Suggested Workflow
  13. Running tests

TestTrack JS Client

This is the JavaScript client library for the TestTrack system.

It provides client-side split-testing and feature-toggling through a simple, mostly declarative API.

This library intends to obscure the details of assignment and visitor session management, allowing you to focus entirely on the experience a visitor should have when she has been assigned a variant.

If you're looking to do server-side assignment and you're using Rails, then check out our Rails client.

Installation

You can add the test track js client to your application via npm, yarn or pnpm.

pnpm add @betterment-oss/test-track

You can find the latest version of the test track JS client here.

Setup

There are two ways to set up TestTrack:

load(options)

Fetches visitor configuration from the TestTrack server and creates a TestTrack instance. This is the recommended approach for most use cases.

import { load, createCookieStorage } from '@betterment-oss/test-track';

const testTrack = await load({
  client: {
    url: 'https://testtrack.example.com',
    appName: 'my_app',
    appVersion: '1.0.0',
    buildTimestamp: '2024-01-01T00:00:00Z'
  },
  storage: createCookieStorage({
    domain: '.example.com'
  })
});

Parameters:

  • client.url - The URL of your TestTrack server
  • client.appName - Your application name
  • client.appVersion - Your application version
  • client.buildTimestamp - The build timestamp (ISO 8601 format)
  • storage - A storage provider for persisting visitor IDs (e.g. createCookieStorage())
  • analytics (optional) - An analytics provider for tracking assignments (see Advanced Configuration)
  • errorLogger (optional) - A function for logging errors

create(options)

Creates a TestTrack instance with preloaded visitor configuration. Use this when you have visitor configuration data available (e.g., from server-side rendering or a cached response).

import { create, createCookieStorage } from '@betterment-oss/test-track';

const testTrack = create({
  client: {
    url: 'https://testtrack.example.com',
    appName: 'my_app',
    appVersion: '1.0.0',
    buildTimestamp: '2024-01-01T00:00:00Z'
  },
  storage: createCookieStorage({
    domain: '.example.com'
  }),
  visitorConfig: {
    splits: [
      {
        name: 'button_color',
        variants: [
          { name: 'blue', weight: 50 },
          { name: 'red', weight: 50 }
        ],
        feature_gate: false
      }
    ],
    visitor: {
      id: 'visitor-uuid',
      assignments: [{ split_name: 'button_color', variant: 'blue' }]
    },
    experience_sampling_weight: 1
  }
});

Parameters:

  • Same as load(), plus:
  • visitorConfig - Preloaded visitor configuration data from the TestTrack API

API

.visitorId

Returns the current visitor's unique identifier as a string. This ID is persisted in the storage provider and used to maintain consistent split assignments across sessions.

console.log(testTrack.visitorId); // "abc123-def456-..."

.vary(split_name, options)

The vary method is used to perform a split. It takes 2 arguments and returns the assigned variant as a string.

  • split_name -- The first argument is the name of the split. This will be a snake_case string, e.g. "homepage_redesign_q1_2015".
  • options -- The second argument is an object that contains the context of the assignment and a default variant (defaultVariant).
    • context -- is a string that the developer provides so that the test track server can record where an assignment was first created. If a call to vary is made in more than one place for a given split, you'll be able to see which codepath was hit first.

    • defaultVariant -- The default variant is used if the user is assigned to a variant that is not defined in the split. When this happens, Test Track will re-assign the user to the default variant. You should not rely on this defaulting behavior, it is merely provided to ensure we don't break the customer experience. You should instead make sure that all variants of the split are handled in your code and if variants are added to the split on the backend, update your code to reflect the new variants. Because this defaulting behavior re-assigns the user to the defaultVariant, no data will be recorded for the unhandled variant. This will impede our ability to collect meaningful data for the split.

Here is an example of a 3-way split where 'control' is the default variant. Let's say 'variant_4' was added to this split on the backend but this code did not change to handle that new variant. Any users that Test Track assigns to 'variant_4' will be re-assigned to 'control'.

const variant = testTrack.vary('name_of_split', { context: 'homepage', defaultVariant: 'control' });

switch (variant) {
  case 'control':
    // do control stuff
    break;
  case 'variant_1':
    // do variant 1 stuff
    break;
  case 'variant_2':
    // do variant 2 stuff
    break;
}

.ab(split_name, options)

The ab method is used exclusively for two-way splits and feature toggles. It takes 2 arguments and returns a boolean.

  • split_name -- The first argument is the name of the split. This will be a snake_case string, e.g. "homepage_chat_bubble".

  • options -- The second argument is an object that contains the context and an optional trueVariant.

    • context -- is a string that the developer provides so that the test track server can record where an assignment was first created. If a call to vary is made in more than one place for a given split, you'll be able to see which codepath was hit first.
    • trueVariant -- an optional parameter that specifies which variant is the "true" variant and the other variant will be used as the default. Without the true variant, ab will assume that the variants for the split are named 'true' and 'false'.
    const hasVariantName = testTrack.ab('name_of_split', { context: 'homepage', trueVariant: 'variant_name' });
    
    if (hasVariantName) {
      // do something
    } else {
      // do something else
    }
    
    const hasFeature = testTrack.ab('some_new_feature', { context: 'homepage' });
    
    if (hasFeature) {
      // do something
    }
    

.logIn(identifier, value)

The logIn method is used to ensure a consistent experience across devices. For instance, when a user logs in to your app on a new device, you should also log the user into Test Track in order to grab their existing split assignments instead of treating them like a new visitor. It takes 2 arguments.

  • identifier -- The first argument is the name of the identifier. This will be a snake_case string, e.g. "myapp_user_id".
  • value -- The second argument is a string value, e.g. "12345", "abcd"
await testTrack.logIn('myapp_user_id', '12345');
// From this point on you have existing split assignments from a previous device.

Advanced Configuration

When you call load() or create() you can optionally pass in an analytics object and an error logger. For example:

const testTrack = await load({
  client: {
    url: 'https://testtrack.example.com',
    appName: 'my_app',
    appVersion: '1.0.0',
    buildTimestamp: '2024-01-01T00:00:00Z'
  },
  storage: createCookieStorage({ domain: '.example.com' }),
  analytics: {
    trackAssignment: (visitorId, assignment) => {
      const props = {
        SplitName: assignment.splitName,
        SplitVariant: assignment.variant,
        SplitContext: assignment.context
      };

      remoteAnalyticsService.track('SplitAssigned', props);
    },
    identify: visitorId => {
      remoteAnalyticsService.identify(visitorId);
    },
    alias: visitorId => {
      remoteAnalyticsService.alias(visitorId);
    }
  },
  errorLogger: message => {
    RemoteLoggingService.log(message); // logs remotely so that you can be alerted to any misconfigured splits
  }
});

Testing

Creates a TestTrack instance for testing with pre-configured assignments and no network requests.

import { stub } from '@betterment-oss/test-track';

const testTrack = stub({
  button_color: 'blue',
  new_feature_enabled: 'true'
});

testTrack.vary('button_color', { context: 'test', defaultVariant: 'red' }); // 'blue'
testTrack.ab('new_feature_enabled', { context: 'test' }); // true

TypeScript

TestTrack supports strict typechecking based on your project's schema.

import { load } from '@betterment-oss/test-track';
import type Schema from './path/to/your/schema.json';

// Pass `Schema` as a type parameter
const testTrack = await load<Schema>({
  /* ... */
});

// Split names and variants are now type-checked
testTrack.vary('button_color', { context: 'home', defaultVariant: 'blue' });
testTrack.ab('new_feature_enabled', { context: 'home' });

Vite Plugin

The @betterment-oss/test-track package includes a Vite plugin that automatically defines import.meta.env.TT_BUILD_TIMESTAMP, which can be used to configure Test Track.

import { defineConfig } from 'vite';
import { testTrackPlugin } from '@betterment-oss/test-track/vite';

export default defineConfig({
  plugins: [testTrackPlugin()]
});

Using TestTrack without a build tool

The @betterment-oss/test-track package is distributed as an ES module. The package also provides dist/index.iife.js. This artifact includes all dependencies and can be used directly in the browser.

<script src="/path/to/index.iife.js"></script>
<script type="module">
  const testTrack = await TestTrack.load({
    client: {
      url: 'https://testtrack.example.com',
      appName: 'my_app',
      appVersion: '1.0.0',
      buildTimestamp: '2024-01-01T00:00:00Z'
    },
    storage: TestTrack.createCookieStorage({
      domain: '.example.com'
    })
  });
  // Use testTrack.vary(), testTrack.ab(), etc.
</script>

How to Contribute

We would love for you to contribute! Anything that benefits the majority of test_track users—from a documentation fix to an entirely new feature—is encouraged.

Before diving in, check our issue tracker and consider creating a new issue to get early feedback on your proposed change.

Suggested Workflow

  1. Fork the project and create a new branch for your contribution.
  2. Write your contribution (and any applicable test coverage).
  3. Make sure all tests pass.
  4. Submit a pull request.

Running tests

  1. run pnpm install to download dependencies
  2. run pnpm test to run the tests
  3. run pnpm build to build the distributables

版本与发布记录

@betterment-oss/test-track 共发布 7 个版本,首次发布于 2026/01/10;过去 12 个月发布了 7 个版本。

版本发布日期距今
5.0.0latest2026/08/252 个月前
4.0.32026/06/194 个月前
4.0.22026/01/239 个月前
4.0.12026/01/239 个月前
3.0.12026/01/239 个月前
4.0.02026/01/229 个月前

关于 @betterment-oss/test-track 的常见问题

@betterment-oss/test-track 是什么?

Javascript Client for Test Track

如何安装 @betterment-oss/test-track?

在项目目录运行 npm install @betterment-oss/test-track,或使用 pnpm add / yarn add / bun add。

@betterment-oss/test-track 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@betterment-oss/test-track 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@betterment-oss/test-track 可以商用吗?

@betterment-oss/test-track 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@betterment-oss/test-track 的下载量有多少?

根据 npm 官方下载统计,@betterment-oss/test-track 在 2026/10/08 – 2026/11/06 这 30 天内被下载 3,934 次,日均约 131 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@betterment-oss/test-track 还在维护吗?

最新版本 5.0.0 发布于 2026/08/25(2 个月前);至今共发布 7 个版本,其中过去 12 个月发布了 7 个;首次发布于 2026/01/10。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。