npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@builder.io/personalization-utils

v4.0.0

Published

Utils for personalization at the edge

Downloads

946

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:

  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 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.