Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions ab-testing/abTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@ const ABTests: ABTest[] = [
groups: ["control", "variant"],
shouldForceMetricsCollection: true,
},
{
name: "thefilter-product-element",
description:
"A hold back test to measure uplift of the product element",
owners: ["thefilter.dev@guardian.co.uk"],
status: "ON",
expirationDate: "2025-12-30",
type: "server",
audienceSize: 0 / 100,
groups: ["control", "variant"],
shouldForceMetricsCollection: false,
},
];

const activeABtests = ABTests.filter((test) => test.status === "ON");
Expand Down
2 changes: 1 addition & 1 deletion ab-testing/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ type AudienceSpace = Map<string, FastlyTestParams>;

type AllSpace = Map<string, FastlyTestParams[]>;

type Team = "commercial" | "webex";
type Team = "commercial" | "webex" | "thefilter";

type TestName = `${Team}-${string}`;

Expand Down
22 changes: 11 additions & 11 deletions dotcom-rendering/docs/development/ab-testing-in-dcr.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ When your PR is merged, the A/B test will be automatically deployed to Fastly an

#### Naming Conventions

A/B tests should be prefixed with the team associated with the test, for example `webex-example-test`. This helps to identify the team responsible for the test and is enforce by typescript validation, you can inspect & edit the allowed team name definitions [here](https://github.com/guardian/dotcom-rendering/blob/main/ab-testing/types.ts#L9).
A/B tests should be prefixed with the team associated with the test, for example `webex-example-test`. This helps to identify the team responsible for the test and is enforced by typescript validation, you can inspect & edit the allowed team name definitions [here](https://github.com/guardian/dotcom-rendering/blob/main/ab-testing/types.ts#L9).

#### Test Size and Groups

Expand All @@ -135,7 +135,7 @@ All requests are processed by Fastly at the edge, however, A/B testing of server

Ensure that the `type` field is set to either `client` or `server` to indicate the type of test so that server side tests can be cached correctly, and client side tests are not splitting the cache unnecessarily.

There's a limit of the number of concurrent server-side tests that can be run, enforce by the validation script, so it's important to use client-side tests where possible.
There's a limit of the number of concurrent server-side tests that can be run, enforced by the validation script, so it's important to use client-side tests where possible.

#### Test Expiration

Expand Down Expand Up @@ -178,13 +178,13 @@ const someComponent = () => {
const abTests = useBetaAB();

// Am I in the test at all?
const isInTest = abTests?.isUserInTest('AbTestTest') ?? false;
const isInTest = abTests?.isUserInTest('webex-example-test') ?? false;

const isInControlGroup =
(abTests?.isUserInTestGroup('AbTestTest', 'control') ?? false);
(abTests?.isUserInTestGroup('webex-example-test', 'control') ?? false);

const isInVariantGroup =
abTests?.isUserInTestGroup('AbTestTest', 'variant') ?? false;
abTests?.isUserInTestGroup('webex-example-test', 'variant') ?? false;

if (isInControlGroup) {
return (
Expand Down Expand Up @@ -223,16 +223,16 @@ const abTests = useBetaAB();
// Get all of the user's server/client-side A/B test participations
const abTestParticipations = abTests?.getParticipations(); // EG. { commercial-dev-client-side-test: 'variant', commercial-dev-server-side-test: 'variant' }

// Is user in the AbTestTest test (any cohort)
const isInTest = abTests?.isUserInTest('AbTestTest') ?? false;
// Is user in the webex-example-test test (any cohort)
const isInTest = abTests?.isUserInTest('webex-example-test') ?? false;

// Is user in the AbTestTest test (control cohort)
// Is user in the webex-example-test test (control cohort)
const isInControlGroup =
abTests?.isUserInTestGroup('AbTestTest', 'control') ?? false;
abTests?.isUserInTestGroup('webex-example-test', 'control') ?? false;

// Is user in the AbTestTest test (variant cohort)
// Is user in the webex-example-test test (variant cohort)
const isInVariantGroup =
abTests?.isUserInTestGroup('AbTestTest', 'variant') ?? false;
abTests?.isUserInTestGroup('webex-example-test', 'variant') ?? false;
```

#### On the Client
Expand Down
17 changes: 15 additions & 2 deletions dotcom-rendering/src/components/ProductElement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { ReactNode } from 'react';
import type { ArticleFormat } from '../lib/articleFormat';
import { parseHtml } from '../lib/domUtils';
import type { NestedArticleElement } from '../lib/renderElement';
import { useBetaAB } from '../lib/useAB';
import type { ProductBlockElement } from '../types/content';
import { ProductCardInline } from './ProductCardInline';
import { ProductCardLeftCol } from './ProductCardLeftCol';
Expand Down Expand Up @@ -39,20 +40,32 @@ export const ProductElement = ({
format: ArticleFormat;
shouldShowLeftColCard: boolean;
}) => {
const abTests = useBetaAB();
const isInHoldBackTestVariant =
abTests?.isUserInTestGroup('thefilter-product-element', 'variant') ??
false;

const showContent =
product.displayType === 'InlineOnly' ||
product.displayType === 'InlineWithProductCard';
// In the hold back test variant, if the product element has a display type of ProductCardOnly,
// we should still render the product card. This is because there may not be any suitable
// nested content to render, which could result in some unintended display issues. For the
// InlineWithProductCard display type, we won't render the cards in the hold back test.
const showProductCard =
product.displayType === 'ProductCardOnly' ||
product.displayType === 'InlineWithProductCard';
(!isInHoldBackTestVariant &&
product.displayType === 'InlineWithProductCard');
return (
<>
{showContent && (
<Content
product={product}
format={format}
ArticleElementComponent={ArticleElementComponent}
shouldShowLeftColCard={shouldShowLeftColCard}
shouldShowLeftColCard={
shouldShowLeftColCard && !isInHoldBackTestVariant
}
/>
)}
{showProductCard && (
Expand Down
Loading