Skip to content

Commit

Permalink
doc: inline documentation in the branch
Browse files Browse the repository at this point in the history
  • Loading branch information
ramboz committed May 29, 2024
1 parent d8ce5c3 commit 5d68204
Show file tree
Hide file tree
Showing 7 changed files with 269 additions and 3 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,6 @@ runEager.call(document, {
```
For detailed implementation instructions on the different features, please read the dedicated pages we have on those topics:
- [Audiences](https://github.com/adobe/aem-experimentation/wiki/Audiences)
- [Campaigns](https://github.com/adobe/aem-experimentation/wiki/Campaigns)
- [Experiments](https://github.com/adobe/aem-experimentation/wiki/Experiments)
- [Audiences](/adobe/aem-experimentation/blob/v1/documentation/audiences.md)
- [Campaigns](/adobe/aem-experimentation/blob/v1/documentation/campaigns.md)
- [Experiments](/adobe/aem-experimentation/blob/v1/documentation/experiments.md)
75 changes: 75 additions & 0 deletions documentation/audiences.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
With audiences you can serve different versions of your content to different groups of users based on the information you can glean from there current session. For instance, you can optimize the experience for:
- mobile vs. desktop
- Chrome vs. Firefox
- 1st vs. returning visitor
- fast vs slow connections
- different ge0graphies
- etc.

## Set up

First, you need to define audiences for the project. This is done directly in the project codebase. Audiences are defined as a `Map` of audience names and boolean evaluating (async) functions that check whether the given audience is resolved in the current browsing session.

You'd typically define the mapping in your AEM's `scripts.js` as follows:
```js
const geoPromise = (async () => {
const resp = await fetch(/* some geo service*/);
return resp.json();
})();

const AUDIENCES = {
mobile: () => window.innerWidth < 600,
desktop: () => window.innerWidth >= 600,
us: async () => (await geoPromise).region === 'us',
eu: async () => (await geoPromise).region === 'eu',
}
```

As you can see in the example above, functions need to return a boolean value. If the value is truthy, the audience is considered resolved, and if it's falsy then it isn't. You can also use any browser API directly, or rely on external services to resolve an audience.

:warning: Using external services will have a performance impact on the initial page load as the call will be blocking the page rendering until the async function is fully evaluated.

The audiences for the project then need to be passed to the plugin initialization as follows:

```js
const { loadEager } = await import('../plugins/experimentation/src/index.js');
await loadEager(document, { audiences: AUDIENCES }, /* plugin execution context */);
```

### Custom options

By default, the audience feature looks at the `Audience` metadata tags and `audience` query parameters, but if this clashes with your existing codebase or doesn't feel intuitive to your authors, you can adjust this by passing new options to the plugin.

For instance, here is an alternate configuration that would use `segment` instead of `audience`:
```js
const { loadEager } = await import('../plugins/experimentation/src/index.js');
await loadEager(document, {
audiences: AUDIENCES,
audiencesMetaTagPrefix: 'segment',
audiencesQueryParameter: 'segment',
}, /* plugin execution context */);
```

## Authoring

Once the audiences made it into the project codebase, your authors are ready to start using audiences for their experiences.
This is done directly in the page metadata block:

| Metadata | |
|-------------------|---------------------------------------------------------------|
| Audience: Mobile | [https://{ref}--{repo}--{org}.hlx.page/my-page-for-mobile]() |
| Audience: Desktop | [https://{ref}--{repo}--{org}.hlx.page/my-page-for-desktop]() |

The notation is pretty flexible and authors can also use `Audience (Mobile)` or `Audience Mobile` if this is a preferred notation.

### Simulation

Once all of this is set up, authors will have access to an overlay on `localhost` and on the stage environments (i.e. `*.hlx.page`) that lets them see what audiences have been configured for the page and switch between each to visualize the content variations accordingly.

![audience overlay](./images/audiences-overlay.png)

The simulation capabilities leverage the `audience` query parameter that is appended to the URL and forcibly let you see the specific content variant.

## Development

To help developers in designing variants for each audience, when audiences are resolved on the page it will automatically add a new CSS class named `audience-<name of the audience>` for each to the `<body>` element, i.e. `audience-mobile audience-iphone`.
60 changes: 60 additions & 0 deletions documentation/campaigns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
With campaigns you can send out emails or social media posts that link back to your site and that will serve specific offers or versions of your content to the targeted audience.

## Set up

The set up is pretty minimal. Once you've instrumented the experimentation plugin in your AEM website, you are essentially good to go.

Just keep in mind that if you want to only target specific audiences for that campaign, you'll also need to set up the [audiences](Audiences) accordingly for your project.

### Custom options

By default, the campaigns feature looks at the `Campaign` metadata tags and `campaign` query parameter, but if this clashes with your existing codebase or doesn't feel intuitive to your authors, you can adjust this by passing new options to the plugin.

For instance, here is an alternate configuration that would use `sale` instead of `campaign`:
```js
const { loadEager } = await import('../plugins/experimentation/src/index.js');
await loadEager(document, {
campaignsMetaTagPrefix: 'sale',
campaignsQueryParameter: 'sale',
}, /* plugin execution context */);
```

:mega: The campaign feature also supports the industry-standard Urchin Tracking Module (UTM) `utm_campaign` as query parameter. There is nothing special you need to do to get this working and it will be seamlessly handled the same way as the `campaignsQueryParameter`. This means that both:

- [https://{ref}--{repo}--{org}.hlx.page/my-page?campaign=xmas]()
- [https://{ref}--{repo}--{org}.hlx.page/my-page?utm_campaign=xmas]()

would essentially serve you the `xmas` variant of the experience.

## Authoring

Once the above steps are done, your authors are ready to start using campaigns for their experiences.
This is done directly in the page metadata block:

| Metadata | |
|---------------------|-----------------------------------------------------------------|
| Campaign: Xmas | [https://{ref}--{repo}--{org}.hlx.page/my-page-for-xmas]() |
| Campaign: Halloween | [https://{ref}--{repo}--{org}.hlx.page/my-page-for-halloween]() |

The notation is pretty flexible and authors can also use `Campaign (Xmas)` or `Campaign Halloween` if this is a preferred notation.

If you wanted to additionally restrict the campaign to specific audiences, so that for instance your campaigns are only accessible on mobile phone or on iPhone, you'd leverage the [audiences](Audiences) feature and use the following metadata:

| Metadata | |
|---------------------|-----------------------------------------------------------------|
| Campaign: Xmas | [https://{ref}--{repo}--{org}.hlx.page/my-page-for-xmas]() |
| Campaign: Halloween | [https://{ref}--{repo}--{org}.hlx.page/my-page-for-halloween]() |
| Campaign Audience | mobile, iphone |

If any of the listed audiences is resolved, then the campaign will run and the matching content will be served.
If you needed both audiences to be resolved, you'd define a new `mobile-iphone` audience in your project and use that in the metadata instead.

### Simulation

Once all of this is set up, authors will have access to an overlay on `localhost` and on the stage environments (i.e. `*.hlx.stage`) that lets them see what campaigns have been configured for the page and switch between each to visualize the content variations accordingly.

![audience overlay](./images/campaigns-overlay.png)

## Development

To help developers in designing variants for each campaign, when a campaign is resolved on the page it will automatically add a new CSS class named `campaign-<name of the campaign>` to the `<body>` element, i.e. `campaign-xmas`.
131 changes: 131 additions & 0 deletions documentation/experiments.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
With experiments (also called A/B tests) you can randomly serve different versions of your content to your end users to test out alternate experiences or validate conversion hypotheses. For instance you can:
- compare how the wording in a hero block impacts the conversion on the call to action element
- compare how 2 different implementations of a specific block impacts the overall performance, engagement and/or user conversion

## Set up

The set up is pretty minimal. Once you've instrumented the experimentation plugin in your AEM website, you are essentially good to go.

Just keep in mind that if you want to only target specific audiences for that experiment, you'll also need to set up the [audiences](Audiences) accordingly for your project.

### Custom options

By default, the experiments feature looks at the `Experiment` metadata tags and `experiment` query parameter, but if this clashes with your existing codebase or doesn't feel intuitive to your authors, you can adjust this by passing new options to the plugin.

For instance, here is an alternate configuration that would use `abtest` instead of `experiment`:
```js
const { loadEager } = await import('../plugins/experimentation/src/index.js');
await loadEager(document, {
experimentsMetaTag: 'abtest',
experimentsQueryParameter: 'abtest',
}, /* plugin execution context */);
```

### Tracking custom conversion events

By default, the engine will consider any `click` a conversion. If you want to be more granular in your tests, you have 2 options available:
1. leverage the `Experiment Conversion Name` property in the metadata
2. Use the https://github.com/adobe/aem-rum-conversion plugin and the experimentation engine will automatically detect its `Conversion Name` property.

## Authoring

Once the above steps are done, your authors are ready to start using experiments for their experiences.
This is done directly in the page metadata block:

| Metadata | |
|---------------------|--------------------------------------------------------------|
| Experiment | Hero Test |
| Experiment Variants | [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-1](), [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-2](), [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-3]() |

The page that is instrumented is called the `control`, and the content variations are `variants` or `challengers`.
Variants are evenly split by default, so the above would give us:
- 25% for the control (the page that has the metadata)
- 25% for each of the 3 variants that are defined

If you want to control the split ratio, you can use:

| Metadata | |
|---------------------|--------------------------------------------------------------|
| Experiment | Hero Test |
| Experiment Variants | [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-1](), [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-2](), [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-3]() |
| Experiment Split | 10, 20, 30 |

This would give us the following split:

- 10% on variant 1
- 20% on variant 2
- 30% on variant 3
- 40% on the control (i.e 100% - 10% - 20% - 30% = 40%)

A `30, 30, 40` split, would respectively give us:

- 30% on variant 1
- 30% on variant 2
- 40% on variant 3
- 0% on the control (i.e 100% - 30% - 30% - 40% = 0%)

which would essentially disable the control page.

If you need to be really granular, decimal numbers are also supported, like `33.34, 33.33, 33.33`.

#### Code-level experiments

Note that the above assumes you have different content variants to serve, but if you want to run a pure code-based A/B Test, this is also achievable via:

| Metadata | |
|---------------------|-----------|
| Experiment | Hero Test |
| Experiment Variants | 2 |

This will create just 2 variants, without touching the content, and you'll be able to target those based on the `experiment-hero-test` and `variant-control`/`variant-challenger-1`/`variant-challenger-2` CSS classes that will be set on the `<body>` element.


#### Audience-based experiments

If you wanted to additionally restrict the experiments to specific audiences, so that for instance your experiment is only run on iPad or on iPhone, you'd leverage the [audiences](Audiences) feature and use the following metadata:

| Metadata | |
|---------------------|--------------------------------------------------------------|
| Experiment | Hero Test |
| Experiment Variants | [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-1](), [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-2](), [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-3]() |
| Experiment Audience | iPad, iPhone |

If any of the listed audiences is resolved, then the experiment will run and the matching content will be served. The list is essentially treated as an "or".
If you needed both audiences to be resolved (i.e. treated as "and"), for say a "US" audience and the "iPad" audience, you'd define a new custom "us-ipad" audience in your project that checks for both conditions and use that in the metadata instead.

#### Time bound experiments

You can also specify start and end dates, as well as toggle the experiment status.

| Metadata | |
|-----------------------|--------------------------------------------------------------|
| Experiment | Hero Test |
| Experiment Variants | [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-1](), [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-2](), [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-3]() |
| Experiment Status | Active |
| Experiment Start Date | 2024-01-01 |
| Experiment End Date | 2024-03-31 |

The status defaults to `Active`, and supports `Active`/`True`/`On` as well as `Inactive`/`False`/`Off`.
Start and end dates are in the flexible JS [Date Time String Format](https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-date-time-string-format). If the start and/or end dates are specified, the experiment will not run if the user's time lies outside the given window.

So you can both use generic dates, like `2024-01-31` or `2024/01/31`, and time-specific dates like `2024-01-31T13:37` or `2024/01/31 1:37 pm`. You can even enforce a specific timezone so your experiment activates when, say, it's 2am GMT+1 by using `2024/1/31 2:00 pm GMT+1` or similar notations.

### Simulation

Once all of this is set up, authors will have access to an overlay on `localhost` and on the stage environments (i.e. `*.hlx.stage`) that lets them see what experiment and variants have been configured for the page and switch between each to visualize the content variations accordingly.

![audience overlay](./images/experiments-overlay.png)

The simulation capabilities leverage the `audience` query parameter that is appended to the URL and forcibly let you see the specific content variant.

### Inline Reporting

AEM Experiments performance is automatically tracked via RUM data, and can be reported directly in the overlay pill UI. Since the RUM data is not public, you'll need to obtain a **domain key** for your website and configure the pill accordingly for the data to show up.

1. Generate a domain key for your site using https://aemcs-workspace.adobe.com/rum/generate-domain-key (make sure to use exactly the same domain name that you used in your project config for go-live)
2. Click the ⚙️ icon in the pill header, and paste the provided domain key in the popup dialog
- alternatively, you can also just run `window.localStorage.setItem('aem-domainkey', <your domain key>)` in the JS console

## Development

To help developers in designing variants for each experiment, when an experiment is running on the page it will automatically add new CSS classes named `experiment-<name of the experiment>` and `variant-<name of the resolved variant>` to the `<body>` element, i.e. `experiment-hero variant-fullpage`.
Binary file added documentation/images/audiences-overlay.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added documentation/images/campaigns-overlay.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added documentation/images/experiments-overlay.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 5d68204

Please sign in to comment.