A/B Testing API: Endpoints and Implementation

React Hooks @pack/hydrogen

These hooks tell your storefront which tests and variants a visitor is in. Use them to send test data to your analytics platform, or to render different code for each variant.

They read Pack's data from your root loader, so it must spread ...context.pack.getPackContextData() into its return value.

useAbTest()

Returns the test the visitor is in, or null if they are not in it.

useAbTest(testHandle?: string): Test | null

  interface Test {
    id: string;
    handle: string;
    testVariant: {
      id: string;
      handle: string;
    };
  }
  • With a test handle (4.0 and later): that test, or null if the visitor is not in it.
  • Without one: the visitor's oldest test.

A test is returned wherever the visitor is, including pages its targeting does not cover, where its content is not being shown.

Example

  import {useAbTest} from '@pack/hydrogen';
  ...

  export function Hero() {
    const heroTest = useAbTest('homepage-hero');

    return heroTest?.testVariant.handle === 'variant-b' ? (
      <p>I am variant B</p>
    ) : (
      <p>I am the control</p>
    );
  }

useAbTests()

Available from @pack/hydrogen 4.0. Returns every test the visitor is in, oldest first, including tests whose targeting does not cover the current page. Returns an empty array when the visitor is in no tests.

useAbTests(): Test[]

import {useAbTests} from '@pack/hydrogen';
...

export function TestTracker() {
    const tests = useAbTests();
    // e.g. send tests.map((test) => test.handle) to your analytics
    return null;
}

useAbTestId()

Returns the id of the test the visitor is in. Takes the same optional test handle as useAbTest.

useAbTestId(testHandle?: string): string | undefined

import {useAbTestId} from '@pack/hydrogen';
...

export function Hero() {
    const testId = useAbTestId('homepage-hero');
    return (
      <div>
        My test ID is: {testId}
      </div>
    );
}

useAbTestHandle()

Returns the handle of the test the visitor is in. Takes the same optional test handle as useAbTest, so it is mostly useful without one, to read the visitor's oldest test.

useAbTestHandle(testHandle?: string): string | undefined

import {useAbTestHandle} from '@pack/hydrogen';
...

export function Hero() {
    const testHandle = useAbTestHandle();
    return (
      <div>
        My oldest test handle is: {testHandle}
      </div>
    );
}

useAbTestVariantId()

Returns the id of the variant the visitor is in. Takes the same optional test handle as useAbTest.

useAbTestVariantId(testHandle?: string): string | undefined

import {useAbTestVariantId} from '@pack/hydrogen';
...

export function Hero() {
    const testVariantId = useAbTestVariantId('homepage-hero');
    return (
      <div>
        My current variant ID is: {testVariantId}
      </div>
    );
}

useAbTestVariantHandle()

Returns the handle of the variant the visitor is in. Takes the same optional test handle as useAbTest.

Always pass the test handle. New tests name their variants control and variant-b, so without one you can read another test's variant-b while the visitor is in control of the test you are branching on.

useAbTestVariantHandle(testHandle?: string): string | undefined

import {useAbTestVariantHandle} from '@pack/hydrogen';
...

export function Hero() {
    const testVariantHandle = useAbTestVariantHandle('homepage-hero');
    return (
      <div>
        My current variant handle is: {testVariantHandle}
      </div>
    );
}

Warnings in development

In development, Pack logs a console warning when:

  • a hook is called without a test handle while the visitor is in more than one test, and
  • a hook is given a test handle but the root loader does not expose Pack's test list. It returns null, so your storefront falls back to its default content.

If the root loader does not spread getPackContextData() at all, useAbTest and the hooks built on it (useAbTestId, useAbTestHandle, useAbTestVariantId, useAbTestVariantHandle) throw ERR_HY_MISSING_AB_TEST_CONTEXT, and useAbTestSessionId throws ERR_HY_MISSING_SESSION_ID. useAbTests returns an empty list instead.

Debugging in the browser

@pack/react adds window.packDebug in the browser:

  • window.packDebug.getTestInfos() lists every A/B test the visitor is in, oldest first (@pack/react 4.6.0 and later).
  • window.packDebug.getTestInfo() returns a single test, as in earlier versions. Prefer getTestInfos().

Manually bucketing yourself into a test

To check a test is working, you can put yourself into a specific test and variant with URL query parameters.

  • Name
    test_handle
    Type
    string
    Description

    The handle of the test.

  • Name
    test_id
    Type
    string
    Description

    The id of the test. Use this or test_handle.

  • Name
    test_variant_handle
    Type
    string
    Description

    The handle of the variant to show, such as control or variant-b.

  • Name
    test_variant_id
    Type
    string
    Description

    The id of the variant to show. Use this or test_variant_handle.

Include one test parameter and one variant parameter, in any combination:

  • ?test_handle=ZZZ&test_variant_handle=YYY
  • ?test_id=ZZZ&test_variant_id=YYY
  • ?test_handle=ZZZ&test_variant_id=YYY
  • ?test_id=ZZZ&test_variant_handle=YYY

Pack also accepts the camelCase and hyphenated spellings, such as testHandle and test-handle.

Was this page helpful?