Skip to content

Commit

Permalink
feat(personaliztion-utils): Add A/B Test Trimming Support to trimHtml…
Browse files Browse the repository at this point in the history
… Function (#3575)

This PR extends the `trimHtml` function to support trimming A/B test
variants in addition to personalization containers.

### Changes:

- Updated `trimHtml` function to process A/B test variants before
personalization containers
- Added `abTests` parameter to `trimHtml` options
- Implemented logic to select winning A/B test variants based on
provided `abTests` object
- Updated README with information on A/B test trimming and usage
examples
  • Loading branch information
teleaziz authored Oct 10, 2024
1 parent c1b329f commit 984cb6f
Show file tree
Hide file tree
Showing 6 changed files with 415 additions and 193 deletions.
47 changes: 38 additions & 9 deletions packages/personalization-utils/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ npm install @builder.io/personalization-utils

# How to start with personalized rewrites?

This utility library helps you encode/decode targeting attributes as parts of the URL to allow for caching (or statically generating) render results, it should be used in middleware in combination with a page path handler (for e.g a catch all page `pages/[[...path]].jsx`):
This utility library helps you encode/decode targeting attributes as parts of the URL to allow for caching (or statically generating) render results, it should be used in middleware in combination with a page path handler (for e.g a catch all page `pages/[[...path]].jsx`):

```ts
import { parsePersonalizedURL } from '@builder.io/personalization-utils/next'
Expand Down Expand Up @@ -62,7 +62,6 @@ export default function middleware(request) {
}
return NextResponse.next();
}

```
```typescript
Expand All @@ -73,22 +72,26 @@ builder.setUserAttributes({ audience })
Once the cookie is set, all builder content matching from now on will weigh in the current audience segment.
## Using trimHtml for Dynamic Containers
## Using trimHtml for Dynamic Containers and A/B Tests
The `trimHtml` function is a utility for handling dynamic personalization containers in your HTML content. It's particularly useful for processing personalized content at the edge or in server-side rendering scenarios.
The `trimHtml` function is a utility for handling dynamic personalization containers and A/B test variants in your HTML content. It's particularly useful for processing personalized content at the edge or in server-side rendering scenarios.
### Usage
```typescript
import { trimHtml } from '@builder.io/personalization-utils'

const fullHTML = '... your full HTML string with personalization containers ...';
const fullHTML = '... your full HTML string with personalization containers and A/B test variants ...';
const userAttributes = {
audience: 'segment-a',
date: '2023-06-15T12:00:00Z'
};
const abTests = {
'content-id-1': 'variant-a',
'content-id-2': 'variant-b'
};

const trimmedHTML = trimHtml(fullHTML, userAttributes);
const { html } = trimHtml(fullHTML, { userAttributes, abTests });
```
To get the `userAttributes`, you should parse the `builder.userAttributes` cookie. Here's an example of how you might do this:
Expand All @@ -104,9 +107,35 @@ function getUserAttributes(req) {

// Then in your request handler:
const userAttributes = getUserAttributes(req);
const trimmedHTML = trimHtml(fullHTML, userAttributes);
```
The `trimHtml` function processes the HTML, evaluates personalization containers against the provided user attributes, and returns a new HTML string with the appropriate personalized content.
To get the `abTests` data, you can parse the relevant cookies like this:
```typescript
import { parse } from 'cookie'

function getAbTests(req) {
const cookies = parse(req.headers.cookie || '');
const abTests = Object.entries(cookies).reduce((acc, [cookieName, cookieValue]) => {
if (cookieName.startsWith('builder.tests')) {
return {
...acc,
[cookieName.split('.').slice(-1)[0]]: cookieValue
}
}
return acc;
}, {});
return abTests;
}

// Then in your request handler:
const abTests = getAbTests(req);
const { html } = trimHtml(fullHTML, { userAttributes, abTests });
```
The `trimHtml` function processes the HTML in the following order:
1. It first applies A/B test variants based on the provided `abTests` object.
2. Then it evaluates personalization containers against the provided user attributes.
3. Finally, it returns a new HTML string with the appropriate personalized content and A/B test variants.
This approach allows you to deliver personalized content while still leveraging edge caching or static site generation, as the personalization logic is applied after the initial HTML is generated.
This approach allows you to deliver personalized content and A/B test variants while still leveraging edge caching or static site generation, as the personalization and A/B test logic is applied after the initial HTML is generated.
4 changes: 2 additions & 2 deletions packages/personalization-utils/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/personalization-utils/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@builder.io/personalization-utils",
"version": "3.0.0",
"version": "4.0.0",
"description": "Utils for personalization at the edge",
"main": "./dist/index.js",
"exports": {
Expand Down
174 changes: 0 additions & 174 deletions packages/personalization-utils/src/get-trimmed-html.test.ts

This file was deleted.

Loading

0 comments on commit 984cb6f

Please sign in to comment.