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.
From @pack/hydrogen 4.0 a visitor can be in several tests at once. Pass the
handle of the test you mean to useAbTest and the hooks built on it. Called
without a handle they return the visitor's oldest test, which may not be
the one on the page. See
Upgrading to @pack/hydrogen 4.0.
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
nullif 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/react4.6.0 and later).window.packDebug.getTestInfo()returns a single test, as in earlier versions. PrefergetTestInfos().
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
controlorvariant-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.