Skip to content

Commit 2baa0d7

Browse files
committed
chore: update to the latest version of the experimentation plugin
1 parent a1c9ca5 commit 2baa0d7

File tree

4 files changed

+204
-88
lines changed

4 files changed

+204
-88
lines changed

plugins/experimentation/src/index.js

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,13 @@ async function replaceInner(path, main) {
8989
const html = await resp.text();
9090
// parse with DOMParser to guarantee valid HTML, and no script execution(s)
9191
const dom = new DOMParser().parseFromString(html, 'text/html');
92-
// eslint-disable-next-line no-param-reassign
93-
main.replaceWith(dom.querySelector('main'));
92+
// do not use replaceWith API here since this would replace the main reference
93+
// in scripts.js as well and prevent proper decoration of the sections/blocks
94+
main.innerHTML = dom.querySelector('main').innerHTML;
9495
return path;
9596
} catch (e) {
9697
// eslint-disable-next-line no-console
97-
console.log(`error loading content: ${plainPath}`, e);
98+
console.log(`error loading content: ${path}`, e);
9899
}
99100
return null;
100101
}
@@ -210,7 +211,7 @@ function inferEmptyPercentageSplits(variants) {
210211
if (variantsWithoutPercentage.length) {
211212
const missingPercentage = remainingPercentage / variantsWithoutPercentage.length;
212213
variantsWithoutPercentage.forEach((v) => {
213-
v.percentageSplit = missingPercentage.toFixed(2);
214+
v.percentageSplit = missingPercentage.toFixed(4);
214215
});
215216
}
216217
}
@@ -240,12 +241,15 @@ function getConfigForInstantExperiment(
240241
variantNames: [],
241242
};
242243

243-
const pages = instantExperiment.split(',').map((p) => new URL(p.trim(), window.location).pathname);
244+
const nbOfVariants = Number(instantExperiment);
245+
const pages = Number.isNaN(nbOfVariants)
246+
? instantExperiment.split(',').map((p) => new URL(p.trim(), window.location).pathname)
247+
: new Array(nbOfVariants).fill(window.location.pathname);
244248

245249
const splitString = context.getMetadata(`${pluginOptions.experimentsMetaTag}-split`);
246250
const splits = splitString
247251
// custom split
248-
? splitString.split(',').map((i) => parseInt(i, 10) / 100)
252+
? splitString.split(',').map((i) => parseFloat(i) / 100)
249253
// even split fallback
250254
: [...new Array(pages.length)].map(() => 1 / (pages.length + 1));
251255

@@ -261,7 +265,7 @@ function getConfigForInstantExperiment(
261265
const vname = `challenger-${i + 1}`;
262266
config.variantNames.push(vname);
263267
config.variants[vname] = {
264-
percentageSplit: `${splits[i].toFixed(2)}`,
268+
percentageSplit: `${splits[i].toFixed(4)}`,
265269
pages: [page],
266270
blocks: [],
267271
label: `Challenger ${i + 1}`,
@@ -435,6 +439,8 @@ export async function runExperiment(document, options, context) {
435439
console.debug(`running experiment (${window.hlx.experiment.id}) -> ${window.hlx.experiment.selectedVariant}`);
436440

437441
if (experimentConfig.selectedVariant === experimentConfig.variantNames[0]) {
442+
document.body.classList.add(`experiment-${context.toClassName(experimentConfig.id)}`);
443+
document.body.classList.add(`variant-${context.toClassName(experimentConfig.selectedVariant)}`);
438444
context.sampleRUM('experiment', {
439445
source: experimentConfig.id,
440446
target: experimentConfig.selectedVariant,
@@ -450,13 +456,18 @@ export async function runExperiment(document, options, context) {
450456
const currentPath = window.location.pathname;
451457
const control = experimentConfig.variants[experimentConfig.variantNames[0]];
452458
const index = control.pages.indexOf(currentPath);
453-
if (index < 0 || pages[index] === currentPath) {
459+
if (index < 0) {
454460
return false;
455461
}
456462

457463
// Fullpage content experiment
458464
document.body.classList.add(`experiment-${context.toClassName(experimentConfig.id)}`);
459-
const result = await replaceInner(pages[index], document.querySelector('main'));
465+
let result;
466+
if (pages[index] !== currentPath) {
467+
result = await replaceInner(pages[index], document.querySelector('main'));
468+
} else {
469+
result = currentPath;
470+
}
460471
experimentConfig.servedExperience = result || currentPath;
461472
if (!result) {
462473
// eslint-disable-next-line no-console
@@ -668,14 +679,25 @@ function adjustedRumSamplingRate(checkpoint, options, context) {
668679
};
669680
}
670681

671-
export async function loadEager(document, options, context) {
672-
document.addEventListener('rum', (event) => {
673-
const checkpoint = event.detail ? event.detail.checkpoint || '' : '';
674-
if(['audiences', 'campaign', 'experiment'].includes(checkpoint)) {
675-
adjustedRumSamplingRate(checkpoint, options, context);
676-
}
677-
});
682+
function adjustRumSampligRate(document, options, context) {
683+
const checkpoints = ['audiences', 'campaign', 'experiment'];
684+
if (context.sampleRUM.always) { // RUM v1.x
685+
checkpoints.forEach((ck) => {
686+
context.sampleRUM.always.on(ck, adjustedRumSamplingRate(ck, options, context));
687+
});
688+
} else { // RUM 2.x
689+
document.addEventListener('rum', (event) => {
690+
if (event.detail
691+
&& event.detail.checkpoint
692+
&& checkpoints.includes(event.detail.checkpoint)) {
693+
adjustedRumSamplingRate(event.detail.checkpoint, options, context);
694+
}
695+
});
696+
}
697+
}
678698

699+
export async function loadEager(document, options, context) {
700+
adjustRumSampligRate(document, options, context);
679701
let res = await runCampaign(document, options, context);
680702
if (!res) {
681703
res = await runExperiment(document, options, context);
@@ -694,9 +716,9 @@ export async function loadLazy(document, options, context) {
694716
if (window.location.hostname.endsWith('.live')
695717
|| (typeof options.isProd === 'function' && options.isProd())
696718
|| (options.prodHost
697-
&& (options.prodHost === window.location.host
698-
|| options.prodHost === window.location.hostname
699-
|| options.prodHost === window.location.origin))) {
719+
&& (options.prodHost === window.location.host
720+
|| options.prodHost === window.location.hostname
721+
|| options.prodHost === window.location.origin))) {
700722
return;
701723
}
702724
// eslint-disable-next-line import/no-cycle

plugins/experimentation/src/preview.css

Lines changed: 110 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -9,40 +9,63 @@
99
* OF ANY KIND, either express or implied. See the License for the specific language
1010
* governing permissions and limitations under the License.
1111
*/
12+
[hidden] {
13+
display: none !important;
14+
}
15+
16+
.hlx-highlight {
17+
--highlight-size: .5rem;
1218

13-
.hlx-preview-overlay {
14-
z-index: 999;
19+
outline-color: #888;
20+
outline-offset: calc(-1 * var(--highlight-size));
21+
outline-style: dashed;
22+
outline-width: var(--highlight-size);
23+
background-color: #8882;
24+
}
25+
26+
.hlx-preview-overlay {
27+
z-index: 99999;
1528
position: fixed;
16-
bottom: 32px;
17-
right: 32px;
1829
color: #eee;
30+
font-size: 1rem;
1931
font-weight: 600;
20-
font-size: 24px;
2132
display: flex;
2233
flex-direction: column;
23-
gap: 16px;
34+
gap: .5rem;
35+
inset: auto auto 1em;
36+
align-items: center;
37+
justify-content: flex-end;
38+
width: 100%;
2439
}
2540

2641
.hlx-badge {
27-
border-radius: 32px;
28-
background-color: #888;
42+
--color: #888;
43+
44+
border-radius: 2em;
45+
background-color: var(--color);
46+
border-style: solid;
47+
border-color: #fff;
2948
color: #eee;
30-
padding: 16px 32px;
49+
padding: 1em 1.5em;
3150
cursor: pointer;
3251
display: flex;
3352
align-items: center;
3453
position: relative;
3554
font-size: inherit;
3655
overflow: initial;
3756
margin: 0;
38-
line-height: 1.5;
57+
justify-content: space-between;
3958
text-transform: none;
40-
font-family: system-ui, sans-serif;
4159
}
4260

4361
.hlx-badge:focus,
4462
.hlx-badge:hover {
45-
background-color: #888;
63+
--color: #888;
64+
}
65+
66+
.hlx-badge:focus-visible {
67+
outline-style: solid;
68+
outline-width: .25em;
4669
}
4770

4871
.hlx-badge > span {
@@ -81,16 +104,22 @@
81104

82105
.hlx-popup {
83106
position: absolute;
84-
bottom: 64px;
85-
right: 0;
107+
display: grid;
108+
grid-template:
109+
"header" min-content
110+
"content" 1fr;
111+
bottom: 6.5em;
112+
left: 50%;
113+
transform: translateX(-50%);
114+
max-height: calc(100vh - 100px - var(--nav-height, 100px));
115+
max-width: calc(100vw - 2em);
116+
min-width: calc(300px - 2em);
86117
background-color: #444;
87-
min-width: 300px;
88118
border-radius: 16px;
89119
box-shadow: 0 0 10px #000;
90120
font-size: 12px;
91121
text-align: initial;
92122
white-space: initial;
93-
line-height: 1.5;
94123
}
95124

96125
.hlx-popup a:any-link {
@@ -100,19 +129,25 @@
100129
display: inline-block;
101130
border-radius: 20px;
102131
text-decoration: none;
103-
word-break: normal;
104132
}
105133

106134
.hlx-popup-header {
107135
display: grid;
136+
grid-area: header;
108137
grid-template:
109-
"label actions"
138+
"label actions"
110139
"description actions"
111140
/ 1fr min-content;
112141
background-color: #222;
113142
border-radius: 16px 16px 0 0;
114143
padding: 24px 16px;
115-
gap: 0 16px;
144+
}
145+
146+
.hlx-popup-items {
147+
overflow-y: auto;
148+
grid-area: content;
149+
scrollbar-gutter: stable;
150+
scrollbar-width: thin;
116151
}
117152

118153
.hlx-popup-header-label {
@@ -129,11 +164,8 @@
129164
flex-direction: column;
130165
}
131166

132-
.hlx-popup h4,
133-
.hlx-popup h5 {
134-
font-family: system-ui, sans-serif;
167+
.hlx-popup h4, .hlx-popup h5 {
135168
margin: 0;
136-
color: inherit;
137169
}
138170

139171
.hlx-popup h4 {
@@ -144,27 +176,22 @@
144176
font-size: 14px;
145177
}
146178

147-
.hlx-popup p,
148-
.hlx-popup code {
179+
180+
.hlx-popup p {
149181
margin: 0;
150-
padding: 0;
151-
background: inherit;
152-
border: inherit;
153-
color: inherit;
154-
font-size: inherit;
155-
line-height: 1.5;
156182
}
157183

158184
.hlx-popup::before {
159-
content: "";
185+
content: '';
160186
width: 0;
161187
height: 0;
162188
position: absolute;
163189
border-left: 15px solid transparent;
164-
border-right: 15px solid transparent;
190+
border-right: 15px solid transparent;
165191
border-top: 15px solid #444;
166192
bottom: -15px;
167-
right: 30px;
193+
right: 50%;
194+
transform: translateX(50%);
168195
}
169196

170197
.hlx-hidden {
@@ -173,28 +200,29 @@
173200

174201
.hlx-badge.is-active,
175202
.hlx-badge[aria-pressed="true"] {
176-
background-color: #280;
203+
--color: #280;
177204
}
178205

179206
.hlx-badge.is-inactive,
180207
.hlx-badge[aria-pressed="false"] {
181-
background-color: #fa0f00;
208+
--color: #fa0f00;
182209
}
183210

184211
.hlx-popup-item {
185212
display: grid;
186213
grid-template:
187-
"label actions"
214+
"label actions"
188215
"description actions"
189216
/ 1fr min-content;
190-
margin: 16px;
191-
padding: 16px;
192-
border-radius: 16px;
193-
gap: 0 16px;
217+
margin: 1em;
218+
padding: 1em;
219+
border-radius: 1em;
220+
gap: .5em 1em;
194221
}
195222

196223
.hlx-popup-item-label {
197224
grid-area: label;
225+
white-space: nowrap;
198226
}
199227

200228
.hlx-popup-item-description {
@@ -215,10 +243,47 @@
215243
flex: 0 0 auto;
216244
}
217245

218-
/* stylelint-disable-next-line media-feature-range-notation */
219-
@media (min-width: 900px) {
246+
@media (width >= 600px) {
247+
.hlx-highlight {
248+
--highlight-size: .75rem;
249+
}
250+
251+
.hlx-preview-overlay {
252+
right: 1em;
253+
align-items: end;
254+
font-size: 1.25rem;
255+
}
256+
257+
.hlx-popup {
258+
right: 0;
259+
left: auto;
260+
transform: none;
261+
min-width: 300px;
262+
bottom: 8em;
263+
}
264+
265+
.hlx-popup::before {
266+
right: 26px;
267+
transform: none;
268+
}
269+
}
270+
271+
@media (width >= 900px) {
272+
.hlx-highlight {
273+
--highlight-size: 1rem;
274+
}
275+
220276
.hlx-preview-overlay {
221-
flex-flow: row-reverse wrap-reverse;
222-
justify-content: flex-start;
277+
flex-flow: row wrap-reverse;
278+
justify-content: flex-end;
279+
font-size: 1.5rem;
280+
}
281+
282+
.hlx-popup {
283+
bottom: 9em;
284+
}
285+
286+
.hlx-popup::before {
287+
right: 32px;
223288
}
224289
}

0 commit comments

Comments
 (0)