@builder.io/personalization-utils
v4.0.0
Published
Utils for personalization at the edge
Downloads
946
Maintainers
Keywords
Readme
Builder Personalization Utils
A collection of handy utilities when working with delivering personalized Builder content at the edge.
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
):
import { parsePersonalizedURL } from '@builder.io/personalization-utils/next'
// in pages/[[...path]].jsx
export async function getStaticProps({ params }) {
const { attributes } = parsePersonalizedURL(params?.path);
const page =
(await builder
.get('page', {
apiKey: builderConfig.apiKey,
userAttributes: attributes,
// cachebust is not advised outside static rendering contexts.
cachebust: true,
})
.promise()) || null
return {
props: {
page,
},
// Next.js will attempt to re-generate the page:
// - When a request comes in
// - At most once every 1 second
revalidate: 1,
}
}
export function getStaticPaths() {
return {
paths: [],
fallback: true,
}
}
export default function Path({ page }) {
return <BuilderComponent model="page" content={page} />
}
Now that we have a path for rendering builder content ready, let's route to it in the middleware:
import { getPersonalizedURL } from '@builder.io/personalization-utils/next'
const excludededPrefixes = ['/favicon', '/api'];
export default function middleware(request) {
const url = request.nextUrl
if (shouldRewrite(url.pathname)) {
const personalizedURL = getPersonalizedURL(request)
return NextResponse.rewrite(personalizedURL)
}
return NextResponse.next();
}
const audience = await myCDP.identifyAudience(userID);
// this will include the `audience` in all api calls and save it in a cookie `builder.userAttributes`
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 and A/B Tests
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
import { trimHtml } from '@builder.io/personalization-utils'
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 { 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:
import { parse } from 'cookie'
function getUserAttributes(req) {
const cookies = parse(req.headers.cookie || '');
const builderAttributes = cookies['builder.userAttributes'];
return builderAttributes ? JSON.parse(builderAttributes) : {};
}
// Then in your request handler:
const userAttributes = getUserAttributes(req);
To get the abTests
data, you can parse the relevant cookies like this:
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:
- It first applies A/B test variants based on the provided
abTests
object. - Then it evaluates personalization containers against the provided user attributes.
- 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 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.