Skip to content

Commit 960530c

Browse files
authored
Merge branch 'main' into doml/subtitles
2 parents 1d9b9ff + ed068ac commit 960530c

File tree

19 files changed

+604
-850
lines changed

19 files changed

+604
-850
lines changed

dotcom-rendering/.storybook/main.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ const config: StorybookConfig = {
2929
{ from: '../src/static', to: '/static/frontend/' },
3030
],
3131

32-
addons: ['@storybook/addon-webpack5-compiler-swc', '@storybook/addon-docs'],
32+
addons: [
33+
'@storybook/addon-webpack5-compiler-swc',
34+
'@storybook/addon-docs',
35+
'@storybook/addon-a11y',
36+
],
3337

3438
webpackFinal: async (config) => {
3539
// Get project specific webpack options

dotcom-rendering/docs/development/ab-testing-in-dcr.md

Lines changed: 82 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -2,87 +2,7 @@
22

33
This document explains how to set up A/B tests in Dotcom Rendering (DCR).
44

5-
## Creating a new A/B test
6-
7-
Create an ab test in [ab-testing/abTest.ts](../ab-testing/abTest.ts) both server and client side tests are defined here. More information on defining tests can be found in [ab-testing/README.md](../ab-testing/README.md).
8-
9-
When the config is merged, the A/B test will be automatically deployed and be available at the same time as your changes.
10-
11-
Ab test on/off state is controlled only by the config. Expired tests will cause the ab testing validation to fail, they will also not be served. In effect expired tests are turned off "automatically", but their config needs to be cleaned up.
12-
13-
The test will appear in https://frontend.gutools.co.uk/analytics/ab-testing once the config is deployed.
14-
15-
## Putting code changes behind an A/B test (group)
16-
17-
### Use in Components
18-
19-
Again, this applies to both client and server side tests.
20-
21-
```ts
22-
// Within the components
23-
import { useBetaAB } from '../lib/useAB';
24-
25-
const someComponent = () => {
26-
// Example usage of AB Tests
27-
const abTests = useBetaAB();
28-
29-
// Am I in the test at all?
30-
const isInTest = abTests?.isUserInTest('AbTestTest') ?? false;
31-
32-
const isInControlGroup =
33-
(abTests?.isUserInTestGroup('AbTestTest', 'control') ?? false);
34-
35-
const isInVariantGroup =
36-
abTests?.isUserInTestGroup('AbTestTest', 'variant') ?? false;
37-
38-
if (isInControlGroup) {
39-
return (
40-
<div>
41-
You're in the control group
42-
</div>
43-
);
44-
} else if (isInVariantGroup) {
45-
return (
46-
<div>
47-
You're in the variant group
48-
</div>
49-
);
50-
} else {
51-
return (
52-
<div>
53-
You're not in the test
54-
</div>
55-
);
56-
}
57-
}
58-
59-
```
60-
61-
### Other ways to check
62-
63-
The ab test API is also available on the window object as `window.guardian.modules.abTests`, this only works client side. It's best to use the `useBetaAB` hook in react components.
64-
65-
Server side tests are also available in the CAPI object e.g. `CAPIArticle.config.serverSideABTests`.
66-
67-
## Forcing yourself into a test
68-
69-
Use the opt-in and opt-out URL fragments to force yourself into or out of a test.
70-
71-
When opted-in, the test will override any mvt based assignment and you'll only be in the opted-in test group.
72-
73-
When opted-out, you'll return to random/mvt based assignment.
74-
75-
These links are also in the [frontend admin](https://frontend.gutools.co.uk/analytics/ab-testing).
76-
77-
- Opt-in Example: `https://theguardian.com/ab-tests/opt/in/commercial-test-example:variant`
78-
- Opt-out: `https://theguardian.com/ab-tests/opt/out`
79-
80-
# Legacy A/B testing in DCR
81-
82-
> [!WARNING]
83-
> This section describes the legacy A/B testing framework in DCR. New A/B tests should use the new A/B testing framework described above.
84-
85-
The documentation remains here for reference, until all legacy A/B tests have ended or have been migrated to the new framework.
5+
There's a new beta A/B testing framework in DCR that supports both client-side and server-side tests with the same API. It's currently in it's beta/testing phase, so please get in touch with the commercial-dev team if you'd like to use it. [Details on how to use the new framework are at the bottom of this document](#beta-ab-test-framework).
866

877
## Client-side A/B tests
888

@@ -157,3 +77,84 @@ You can verify that you have been correctly assigned to the variant by appending
15777
```
15878

15979
You can access server-side `abTests` within DCR wherever the CAPI object is used (`CAPIArticle.config.abTests`).
80+
81+
# Beta AB Test framework
82+
83+
This is a new framework that has been developed by commercial-dev to support both client and server side A/B tests in DCR. The goal is to eventually replace the legacy A/B testing framework described above with this new framework.
84+
85+
Please get in touch with the commercial-dev team if you'd like up to date information on it's state of readiness.
86+
87+
## Creating a new A/B test
88+
89+
Create an ab test in [ab-testing/abTest.ts](../ab-testing/abTest.ts) both server and client side tests are defined here. More information on defining tests can be found in [ab-testing/README.md](../ab-testing/README.md).
90+
91+
When the config is merged, the A/B test will be automatically deployed and be available at the same time as your changes.
92+
93+
Ab test on/off state is controlled only by the config. Expired tests will cause the ab testing validation to fail, they will also not be served. In effect expired tests are turned off "automatically", but their config needs to be cleaned up.
94+
95+
The test will appear in https://frontend.gutools.co.uk/analytics/ab-testing once the config is deployed.
96+
97+
## Putting code changes behind an A/B test (group)
98+
99+
### Use in Components
100+
101+
Again, this applies to both client and server side tests.
102+
103+
```ts
104+
// Within the components
105+
import { useBetaAB } from '../lib/useAB';
106+
107+
const someComponent = () => {
108+
// Example usage of AB Tests
109+
const abTests = useBetaAB();
110+
111+
// Am I in the test at all?
112+
const isInTest = abTests?.isUserInTest('AbTestTest') ?? false;
113+
114+
const isInControlGroup =
115+
(abTests?.isUserInTestGroup('AbTestTest', 'control') ?? false);
116+
117+
const isInVariantGroup =
118+
abTests?.isUserInTestGroup('AbTestTest', 'variant') ?? false;
119+
120+
if (isInControlGroup) {
121+
return (
122+
<div>
123+
You're in the control group
124+
</div>
125+
);
126+
} else if (isInVariantGroup) {
127+
return (
128+
<div>
129+
You're in the variant group
130+
</div>
131+
);
132+
} else {
133+
return (
134+
<div>
135+
You're not in the test
136+
</div>
137+
);
138+
}
139+
}
140+
141+
```
142+
143+
### Other ways to check
144+
145+
The ab test API is also available on the window object as `window.guardian.modules.abTests`, this only works client side. It's best to use the `useBetaAB` hook in react components.
146+
147+
Server side tests are also available in the CAPI object e.g. `CAPIArticle.config.serverSideABTests`.
148+
149+
## Forcing yourself into a test
150+
151+
Use the opt-in and opt-out URL fragments to force yourself into or out of a test.
152+
153+
When opted-in, the test will override any mvt based assignment and you'll only be in the opted-in test group.
154+
155+
When opted-out, you'll return to random/mvt based assignment.
156+
157+
These links are also in the [frontend admin](https://frontend.gutools.co.uk/analytics/ab-testing).
158+
159+
- Opt-in Example: `https://theguardian.com/ab-tests/opt/in/commercial-test-example:variant`
160+
- Opt-out: `https://theguardian.com/ab-tests/opt/out`

dotcom-rendering/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@
4343
"@guardian/shimport": "1.0.2",
4444
"@guardian/source": "11.3.0",
4545
"@guardian/source-development-kitchen": "18.1.1",
46-
"@guardian/support-dotcom-components": "7.10.1",
46+
"@guardian/support-dotcom-components": "8.0.0",
4747
"@guardian/tsconfig": "0.2.0",
4848
"@playwright/test": "1.56.1",
4949
"@sentry/browser": "10.20.0",
50+
"@storybook/addon-a11y": "9.1.13",
5051
"@storybook/addon-docs": "9.1.13",
5152
"@storybook/addon-webpack5-compiler-swc": "4.0.1",
5253
"@storybook/react-webpack5": "9.1.13",
@@ -176,6 +177,6 @@
176177
"webpack-messages": "2.0.4",
177178
"webpack-node-externals": "3.0.0",
178179
"webpack-sources": "3.3.3",
179-
"zod": "3.22.4"
180+
"zod": "4.1.12"
180181
}
181182
}

dotcom-rendering/src/client/sentryLoader/sentryLoader.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ describe('Enable Sentry when it passes loading conditions', () => {
3434
}),
3535
).toEqual(true);
3636
});
37-
it('does enable Sentry for 1% of users', () => {
37+
it('does enable Sentry for 0.1% of users', () => {
3838
expect(
3939
isSentryEnabled({
4040
isDev: false,
@@ -56,7 +56,7 @@ describe('Enable Sentry when it passes loading conditions', () => {
5656
isDev: false,
5757
enableSentryReporting: true,
5858
isInBrowserVariantTest: false,
59-
random: 99.0001 / 100,
59+
random: 99.9001 / 100,
6060
}),
6161
).toEqual(true);
6262
expect(

dotcom-rendering/src/client/sentryLoader/sentryLoader.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ const isSentryEnabled = ({
2424
if (isInBrowserVariantTest) return true;
2525
// Sentry lets you configure sampleRate to reduce the volume of events sent
2626
// but this filter only happens _after_ the library is loaded. The Guardian
27-
// measures page views in the billions so we only want to log 1% of errors that
27+
// measures page views in the billions so we only want to log 0.1% of errors that
2828
// happen but if we used sampleRate to do this we'd be needlessly downloading
29-
// Sentry 99% of the time. So instead we just do some math here and use that
29+
// Sentry 99.9% of the time. So instead we just do some math here and use that
3030
// to prevent the Sentry script from ever loading.
31-
if (random <= 99 / 100) return false;
31+
if (random <= 999 / 1000) return false;
3232
return true;
3333
};
3434

0 commit comments

Comments
 (0)