How to Personalize Content & Jamstack Web Experiences with Uniform & Next.js

Building apps on the Jamstack gives us fast and reliable apps, but just because our front end may be static, doesn’t mean it can’t be dynamic. How can we use Uniform to give the control of content back to those who actually manage the content and add a personalization layer to our Jamstack apps with a more dynamic and effective experiences?

What's Inside 🧐

View on YouTube

Disclaimer: This is a sponsored post by Uniform. Learn more about spacejelly.dev and sponsored content.

Moving away from the traditionally coupled approach, the Jamstack ideology went the opposite direction decoupling services with proven tech. While there are a lot of benefits to this, things were lost in this transition, such as now requiring developers to make changes to content instead of a friendly CMS or experimentation like A/B testing which often require code changes.

As developer friendly as the Jamstack is, this took the control away from the people who actually work with those tasks day-to-day, adding more time, money, or a constant fight trying to make older tools work with modern solutions.

This is where Uniform comes in, bringing together the best parts of modern architectures like the Jamstack while still giving business users the tools they need, restoring the balance between developer happiness and user productivity.

What is Uniform?

Uniform is a Digital Experience Platform (DXP) that gives you the ability to assemble your own building blocks of the web including headless content management, headless commerce, modern CDNs, front end frameworks, and personalization under one powerful umbrella.

But what makes Uniform interesting is not only do they provide a lot of features themselves, they have integrations with other individual tools like content from Contentful, ecommerce with BigCommerce, or data with Google Analytics, that makes that assembly quick and easy.

Once set up, Uniform is able to pull together all of those sources including the content and data into a “mesh” that’s easily consumable by your app. That means, instead of having to make a variety of requests to all your different sources, you can make a single one right to Uniform.

Taking this a step further, Uniform pools all of this content and data together to give you the ability to optimize your visitor’s experiences with no-code tools that developers or business users can use to build personalized pages.

What do I mean by personalization?

At it’s simplest, personalizing a web experience means changing something dynamically based some small detail about that visitor.

That could range from what page that person last visited or what button they clicked. It could even be detailed recommendations based on how they’ve interacted with your app.

In the context of ecommerce and an online store, if you have a customer who has an account and has been shopping with you for a long time, you likely know based on their account history what they’ve purchased before. That information can be used to suggest products that you think they may like.

Whether it’s a small or big change, using that information is helpful for giving your visitors a better experience.

What are we going to build?

To get started with Uniform, we’re going to jump into how we can source content from Uniform and personalize that content based on our visitor.

Our project will be a simple blog where we’ll feature a newsletter signup for new visitors. If we’re sending existing subscribers to our blog though, we probably don’t want to try to get them to sign up again, so why not show something else like following us on social media?

We’ll do this by spinning up a simple Next.js React application based on a demo Starter I’ve already created. Once we’re ready to go, we’ll learn how to move our newsletter signup into Uniform, configure it in our project, and personalize our call to action by looking at a URL parameter.

To follow along, you’ll need a Uniform account. You can sign up for a free account over at uniform.dev.

Step 0: Creating a new Next.js app from a demo starter

We’re going to start off with a new Next.js app that simply lists some of my posts from spacejelly.dev on the homepage. Above those posts is a Newsletter Signup Call to Action (CTA), which is what we’ll use to learn how to personalize with Uniform.

Inside of your terminal, run:

yarn create next-app my-uniform-blog -e https://github.com/colbyfayock/demo-blog-home-starter
# or
npx create-next-app my-uniform-blog -e https://github.com/colbyfayock/demo-blog-home-starter

Note: feel free to use a different value than my-uniform-blog as your project name!

Once installation has finished, you can navigate to that directory and start up your development server:

cd my-uniform-blog

yarn dev
# or
npm run dev

And once loaded, you should now be able to open up your new app at http://localhost:3000!

Website with My Space Jelly blog including newsletter signup and blog posts
New Next.js website

Before we dive in, the most important part to get familiar with in this project is the homepage file inside pages/index.js.

We’ll be working within this page (along with _app.js) to personalize the Newsletter Signup section, which you can find under the h1 title.

The rest of the content is pretty much placeholder to give us a basic understanding of how this works in the context of the rest of the page!

Step 1: Setting up a new Uniform Project

The first thing we’ll do to get started with Uniform is to recreate our existing content. Particularly, we’ll recreate our Newsletter Signup form including creating a Component for that placement along with a Composition, which will contain our Components, as well as other future ones we may add.

Before we jump in though we’ll need to create a new Project.

If this is your first time creating your account, you’ll be prompted with a warm welcome where you can also accept the terms.

But once you’re in the Uniform dashboard on the Projects page, click the big plus button (+) to create a new Project.

Uniform dashboard with button to create a new Project
Creating a new Uniform Project

Here we have a few options:

  • Project Name: whatever you’d like to name this project, I’m going to call mine My Blog
  • Deploy a Demo: this gives us the ability to deploy a project with existing content, we’re going to skip this
  • Set Up a New Project: we can either use a guided setup or create an empty Project, but because I’m walking you through myself, let’s choose Empty

Once your options are selected, we can click Continue to move on.

New Project creation wizard selecting Empty project
Creating an empty Project

At this point we have our new Uniform Project, so we can now get started building out our experience.

Step 2: Creating a new Uniform Component for a Call to Action

As alluded to earlier, we need to create two parts to our Project: our Composition and our Component. First we’ll build our Component which we’ll later add to our Composition.

The Component will be our Signup widget, where we’ll be able to generalize that section to show whatever we want dynamically.

So to get started, navigate to the Canvas tab then select the Component Library section in the sidebar. Here, we’ll click the big red plus button to create a new Component.

Canvas dashboard with highlighted buttons to navigate to and create a new Component
Navigating to create a new Component

Here we have a few configurations we need to add, including:

  • Component Name: what you’ll refer to your Component as, I’m going to use “Call to Action”
  • Public ID: this autofills based on the Name, which we can leave “as is” (ex: “callToAction”) unless you prefer it different
  • Composition Component: this should NOT be checked, we’ll use this later when creating our Composition

The rest of the top configurations are optional and you can really configure it however you’d like, but we won’t need anything else for our Composition.

Add Component UI setting up Call to Action
Creating a Call to Action Component

Before we Save though, we need to configure Parameters.

You can think of Parameters as props in a react context or generally individual pieces of data that we’ll use to create our Call to Action dynamically.

Click the big red plus button under the Parameters section at the bottom where we’ll have a few pieces of information we’ll want to fill out. We’ll want to do this for each parameter we’ll add.

For our Call to Action, we’re going to set up 4 parameters:

  • Headline: the big text that will grab someone’s attention
  • Body: the longer text that will
  • Link URL: where our call to action will link to
  • Link Title: what our call to action button will say

You can use the names above for creating each parameter, keeping the auto generated Public ID, and selecting the Text for the Parameter Type.

Add Parameter UI showing adding a Headline Parameter
Creating a new Parameter

You can optionally require each parameter and set up a Validation method, but we’ll skip that for now.

Once done, we should have our 4 new Parameters.

Tip: while we’re keeping things simple for this walkthrough and setting up our Parameters right inside Uniform, this becomes much more powerful when you connect these fields to your headless CMS such as integrating with Contenful!

Component creation page showing 4 Parameters
Adding Parameters to a Component

Now you can scroll back up on the page and click Save and close.

That will give us our Call to Action Component!

Next we’ll learn how to use that Component in a Composition.

Step 3: Creating a new Composition in Uniform

Now that we have our Component, we can get started building a Composition.

Technically a Composition is a Component at its core, where a Composition is an instance of a Component. The hope is with this model, we can make it easier on ourselves and give people who are non-technical the ability to create these without having to mess with the wiring under the hood.

You can think of Composition in this context like a page, though you can really base your Composition off of whatever you want. We’ll create our Composition as our Homepage, which includes our Call to Action Component.

Navigate back over to the Component Library section and click the big red plus button to create a new component.

Here we’ll create our Component somewhat similarly to Step 2, but this time we want to create a Composition.

This means, importantly, we want to make sure Composition Component is checked.

For the name name, we can use Page, where our Homepage will be an instance of this Page.

Component creation screen showing Page used as a Composition Component
Creating a new Composition Component

Before we click Save, we have one more thing to do.

Instead of adding Parameters, this time we need to add a Slot.

By using Slots within our Composition, we add the ability to dynamically place any number of components within that Slot without having to make any changes to the code. This means we have and can give full control over that portion of the page (or even a whole page) to those who need to make the changes.

Note: Slots are actually a requirement in Uniform to be able to add personalization to a Composition.

Navigate to the Slots section at the bottom then click the big red plus button.

While you can use Slots however you’d like, you can think of a Slot as a particular area or section to your Composition.

In our context, our Composition is a Page. On our Page, the section that we want to add our Call to Action to could be described as Promo which could include things like our newsletter signup or other promotional things, so let’s call it that.

Next we want to configure how our Slot works:

  • Required Component Quantity: how many different components should we allow to show? Only one might make sense in our case, so let’s say minimum of 0 and maximum of 1
  • Allowed Components: what components do we want to actually allow in our Slot? We want to make sure we select Call to Action, but we also want to later personalize this section, so let’s also select Personalization, which will give us that ability to personalize this particular Slot
Slot creation UI showing adding a Promo slot with allowed Call to Action and Personalization
Adding a new Slot

Once done, we can hit OK, for our Slot, then click Save and close at the top of our Add Component page!

Next we want to add our new Composition.

Navigate to the Compositions section in the sidebar, click the big red plus button.

Here we’ll set up our actual Composition. First, select our Page Composition Component type, give the Composition a name such as “Homepage”, then click Create.

Add a composition UI with highlighted buttons to navigate and create
Creating a new Composition

Once you click Create, you’ll be dropped into the Composition editor, or “Canvas”.

Here we can see the hierarchy of our Composition, where we have our Page, our Slot (Promo), where we can now add our Components.

Click the green plus button under Page and Promo where we’re given the ability to add a Component.

Select the Call to Action Component where then, we’ll now see fields where we can which represents the parameters we created in the previous step.

For each of these parameters, let’s recreate this Call to Action Component exactly how it exists in our current application:

  • Headline: Sign up for my newsletter!
  • Body: Get the latest tutorials straight to your inbox.
  • Link URL: https://colbyfayock.com/newsletter (you can replace this with your own Newsletter link, or you can use mine to follow along)
  • Link Title: Learn More

Note: in a real-world scenario, you would like want this coming from a headless CMS like Sanity, meaning you wouldn’t see the editable text parameters like we do here.

Composition configuration page showing adding a Call to Action Component to the Page Promo Slot
Adding a Component to a Composition

Now before we save, we have one more thing we want to do.

In the top left of the page, we should see an action link that shows Add a slug. The Slug is what we’ll use to programmatically look up this composition later.

Tip: Slugs are optional and you could query by ID (like in the URL), but adding a Slug is a a bit friendlier

Click Add a slug and name it something unique such as “homepage”.

But now, not only do we want to Save our Composition, we want to Publish it, so click the little arrow next to the Save button, then select Save and publish.

Composition page showing Save dropdown with Save and publish
Saving and publishing a Composition

Tip: not quite ready to hit Publish? Once saved, you can also access all Drafts with the Uniform API

At this point, we have Composition configured with our Component, and we’re now ready to get started adding it to our app!

Step 4: Installing and configuring Uniform Canvas in a Next.js app

With our Composition and Component ready to go, we can get started setting up our app to dynamically pull in our content.

Back in our project, we first need a few packages. Run the following in your terminal:

yarn add @uniformdev/canvas @uniformdev/canvas-react

Once installed, we can dive into our code editor.

We’ll be setting up our Signup widget on the homepage, so let’s open up our homepage at pages/index.js.

Here we need to import our components, so add the following to the top of pages/index.js:

import { CanvasClient } from '@uniformdev/canvas';
import { Composition, Slot } from '@uniformdev/canvas-react';

Now, to get our data from Uniform into our application, we need to use the CanvasClient we just imported to request that data.

Next.js has a few different options for how we’ll fetch data, but we’ll use getStaticProps, since we only need to pull in our default content during compile.

To do this, we need to define our getStaticProps function, so at the bottom of pages/index.js under our Home component, let’s add:

export async function getStaticProps() {
  return {
    props: {}
  }
}

Inside getStaticProps, we want to first configure our CanvasClient which we’ll use to request our content.

At the top of getStaticProps add:

const client = new CanvasClient({
  apiKey: process.env.UNIFORM_API_KEY,
  projectId: process.env.UNIFORM_PROJECT_ID,
});

If you notice, we’re using environment variables to define our API Key and Project ID, we’ll set that up in a second, but for now, let’s add the rest of the request to get our data.

After where we defined our client, add:

const { composition } = await client.getCompositionBySlug({
  slug: 'homepage',
});

Here, we’re using the getCompositionBySlug method to access our Uniform Composition. If you’re instead using the ID, you can alternatively use getCompositionById.

Note: if you used a different Slug when creating your Composition, make sure to update that here!

And finally, we can pass that as a prop to our application by updating our return statement:

return {
  props: {
    composition
  }
}

Now, as I mentioned before, we’re using environment variables to access our API Key and Project ID, meaning, we need to create those variables for it to work.

First, let’s create a new file in the root of our project called .env.

Note: it’s important that we use .env, not .env.local to be sure Uniform can find our API Key and Project ID

Inside .env add:

UNIFORM_API_KEY="[Your API Key]"
UNIFORM_PROJECT_ID="[Your Project ID]"

Tip: before we do anything else, please go to .gitignore and make sure .env is inside to avoid committing your credentials to GitHub!

To find those values, let’s head back over to our Uniform dashboard, where first, let’s find our API Key.

Navigate to the API Keys page by first clicking on your Team Name at the top left of the Uniform dashboard, then select Settings, and then API Keys in the sidebar.

API Keys page in Uniform dashboard with highlighted navigation to create a new key
Creating a new API Key

Once there, click the big red button to create a new API key.

A new screen will open with a few things to configure:

  • Name: this should be some kind of description that you can use to describe your API Key function, such as the project name, or “Development”, really whatever will help you remember what it is. I’m going to call it “My Blog”
  • Add permissions to a new project: this is where you’ll select what Projects this key will have access to, which we want to add the Project we’ve been working on, so click the dropdown and select the Project name (mine is My Blog)

After adding the Project, you’ll now have the ability to add permissions to different capabilities. We’ll want to make sure we add the following permissions:

  • Uniform Canvas > Compositions > Read Draft
  • Uniform Canvas > Compositions > Read Published
  • Uniform Optimize > Intent Manifest > Read

Note: we’ll be using the Uniform Optimize permission later, but this way we won’t have to come back and add it in another step.

API Key creation showing permissions to add and name
Creating a new API Key

Then scroll to bottom and click Create.

Uniform will then show you your API Key. Make sure to copy this and save it for later use, as this will be the only time you’ll be able to see it (otherwise you’ll need to create a new one).

Note: you can optionally copy your Project ID here, but next we’ll show how to find that without creating a new key.

Update UNIFORM_API_KEY inside of .env with your API Key.

To find your Project ID, you can then navigate to Projects then in the card that has your Project name, click the three dots and select Settings or navigate to the Setting section of your Project..

If you scroll down to the bottom of the General page, you’ll see your Project ID, which you can copy into your app.

Update UNIFORM_PROJECT_ID inside of .env with your Project ID.

But now, our project should be configured, so let’s see if it’s working.

Head up to the top of pages/index.js and inside of the arguments of the Home component, let’s add a new prop and immediately add a console.log for it:

export default function Home({ composition }) {
  console.log('composition', composition)

If we now open up our app in the browser and look inside of the web console, we should now see all of our data logged out!

Chrome web console showing logged out Composition data
Composition data in web console

Now we can wire up our application to use that content.

Earlier, we imported the Composition and Slot components from Uniform, which is what we’ll use to set up our Signup widget.

To do this, replace the Signup widget with the following and we’ll explain what’s happening after:

<Composition data={composition} resolveRenderer={() => {
  const DefaultComponent = ({ headline, body, linkUrl, linkTitle }) => {
    return (
      <div className={styles.signup}>
        <div className={styles.signupBody}>
          <h2>{ headline }</h2>
          <p>{ body }</p>
        </div>
        <div className={styles.signupCta}>
          <p>
            <a href={linkUrl}>{ linkTitle }</a>
          </p>
        </div>
      </div>
    );
  };
  return DefaultComponent;
}}>
  <Slot name="promo" />
</Composition>

In the above, we’re:

  • Wrapping our Signup widget with a Composition component
  • We’re setting 2 props, data which is our composition data that we received from Uniform and resolveRenderer which will be a React component that renders the UI
  • Inside resolveRenderer we’re creating a new component which includes the same code as our original widget, but we’re replacing the content with props that match the parameters we created for the Call to Action Component in Uniform
  • Finally, we’re nesting the Slot component giving the name of the Slot we created for our Composition inside of Uniform

And with all of that, our page should look exactly the same as it did in Step 1, but it should now be dynamically pulled in from Uniform!

Website showing terminal with overlaid text showing where each parameter matches up to from the Composition Slot
Dynamic component with Composition Slot parameters

While this alone gives us a lot of flexibility for managing our content, next we’ll learn how we can take this up another level and personalize this content based on our visitor.

Follow along with the commit!

Step 5: Setting up a new Uniform Intent for personalized content

Part of what makes Uniform so powerful is we’re able to take our already dynamic experiences and personalize them to our visitors.

This can mean a wide variety of things including recommending different products based on what your visitor likes or targeting critical information based on what we know about them.

In our example, we’re going to set up our Call to Action widget to dynamically show three experiences based on whether or not they have a URL parameter.

Note: You can create signals using much more than just a URL parameter, but it’s a great example to get started learning how it works!

Particularly, here are the scenarios:

  • Visitor without matching URL parameter: default newsletter signup
  • Visitor with matching URL parameter utm_source=newsletter: follow on social media
  • Visitor with matching URL parameter utm_campaign=jamstack: check out my book

In order to do this, we need to create an Intent.

Intents involve two important concepts: the Intent itself and Signals. When we’re configuring our Intents, we create Signals that ultimately tell Uniform whether or not that Intent matches the visitor.

As a quick example, which we’ll soon set up, if have my newsletter signup form on the homepage of spacejelly.dev, I may not want to show that form if the person is already signed up for my newsletter. Instead, maybe I can show them links to follow me on social media.

In this example, I may have an intent called “Follow on Social Media”. If I set up all links in my newsletter to include a parameter of utm_source=newsletter, I’ll know that’s where they came from. I can use that as a Signal to tell Uniform that it’s a strong indicator that I should be showing my “Follow on Social Media” experience.

So let’s get started actually building this group of Intents and Signals to see how it works in practice.

Navigate to the Personalization section of our Project and click the big red plus button to create a new Intent.

We have a few things to configure, but we really only need to be concerned with our Name, our Public ID which will autogenerate as usual, and the Description can be whatever helps you remember what the Intent is about.

Our first Intent is going to be that we want to show social media links to current newsletter subscribers, so to get started we can name this “Follow on Social Media”.

New Intent UI showing Follow on Social Media name
Adding a new Intent

Once ready, click Save.

Next, we need to define Signals, which help Uniform determine how we know our visitor matches the type of visitor we intend to show our Intent to such as someone who is already a subscriber to our newsletter.

Each Signal that we define further strengthen’s Uniform’s ability to correctly determine the type of visitor. When adding multiple Intents, it will use those Signals to try to see which Intent makes the most sense based off of all Signals it receives.

So to get started, click the big red plus button to add a new Signal to our Intent.

Here we have a lot of options available to use but in our example we’re going to use Query String which will then take you to the Query String configuration page.

Signal creation selecting the Query String type of Intent
Creating a new Signal

Here we have a few things to configure:

  • Name: this is the name that we’ll give to our Signal, which in our case, we’re looking for a URL parameter that signifies that our visitor came from our newsletter, so let’s call this “Is From Newsletter”
  • Signal Type: we just selected Query String, let’s leave this for now
  • Query string parameter: what parameter we’re looking for in the URL, which in our case we’re going to look for a parameter name of utm_source that equals the parameter value of newsletter (optionally you can make this case sensitive, but I don’t recommend it unless you know what you’re doing)
Add Signal UI showing configuration of newsletter parameter
Signal configuration

We can leave the rest of the configurations as is, but here’s what they mean:

  • Signal Effect: when our visitor comes to our site, they’ll have a “score” which is how Uniform keeps track which Intent fits them. We can set up our Signal not only to increase that score, but decrease it as well, and configure how much it does increase or decrease it. In our case we want it to increase
  • Signal Effect: we can also make it so that score is changed only for that one visit or forever. Since we want to be able to use that Intent, it probably makes sense to keep it as forever
  • Trigger Frequency: we can set up how often the Signal gets increased or decreased when our visitor arrives on our site

But now we’re ready to go and we can click Save!

Next, let’s add our second Intent, which is to show a product related to a campaign we’re running, which in our example we’ll use a campaign of Jamstack that will be showing a link to a Jamstack book.

Follow the same steps we did above to create a new Intent called “Check Out Jamstack Book” with one Signal with the following configuration:

  • Name: Jamstack Campaign
  • Signal Type: Query String
  • Query String Parameter: utm_campaign=jamstack
  • Leave the other configurations as defaults, meaning it will increase the visitors “score”

Similar to before, we’re telling Uniform that when our visitor matches this Signal, we want to show that specific intent. We know we’re marketing content as part of our Jamstack campaign, so by showing Jamstack-related products (the book), we’re personalizing the content based on what we know our visitor is interested in.

Want to level up from Developer to “Experience Engineer”? Learn more about personalization strategy, implementation, and how it helps engagement with Uniform’s Personalization Strategy Workbook.

Finally, as one last step for creating our Intents, we need to publish them.

Head over back to the Personalization section, where at the top right of the page, we simply want to click Publish.

Personalization page with Intents with highlighted Publish button
Publishing Intents

Next we’ll learn how to use our new Intent to create a dynamic experience with our Call to Action.

Step 6: Adding a new Call to Action and experience based on an Intent in Uniform

With our new Intent, we can now configure our Composition Slot to dynamically show content based on our visitor.

To do that, let’s head back over to the Canvas section and navigate to our Homepage Composition.

Here, we want to configure our Call to Action Component inside of our Promo slot to be personalized.

Click on the Call to Action component, then on the right, click Personalize This.

Composition configuration page showing Call to Action nested under Personalization section
Personalizing Call to Action component

Here you’ll notice 2 things:

  • The structure on the left now shows our Call to Action nested under a Personalization section
  • We can now select an Intent Tag in our Component configuration

In our case, we’re going to NOT add an Intent Tag to our default component, as we want that experience to appear if we don’t know anything about our visitor.

Instead, we’re going to add another Component with an Intent.

If you hover over the top or bottom of the Call to Action component, you should notice a green plus button.

Highlighted green plus button used for creating a new Personalized Component
Creating a new Personalized Component

Go ahead and click the green button which will open a list of Components we can choose from (or one if this is your first time using Uniform).

Here we can go ahead and select the same Call to Action component from our list which will then open up a configuration page.

This is going to serve as our personalized Component that’s going to show whenever our visitor matches our Intent, so let’s define it as the following:

  • Headline: Get updates straight from Twitter!
  • Body: Don’t want to wait for the weekly newsletter? Follow me on Twitter to get live updates.
  • Link URL: https://twitter.com/colbyfayock
  • Link Title: Follow on Twitter

Note: of course make sure to update all of this with your own information or feel free to use mine just to follow along!

Now before we save, we want to add our Intent.

Click the Add Intent Tag dropdown where we should see and be able to select our Follow on Social Media Intent.

Composition configuration showing new personalized Component using Follow on Social Media Intent
Creating a Component with an Intent to Follow on Social Media

Once selected, you should now see that the selected call to action in our page structure now shows that it’s tagged with our Intent!

Now let’s add our third Component experience for our Jamstack Campaign.

Similar to before, create a new Component in the Homepage Promo CTA section with the following configuration:

  • Headline: Learn more about the Jamstack!
  • Body: Dive into everything there is to know about the Jamstack with this book.
  • Link URL: https://jamstackhandbook.com/
  • Link Title: Learn More
  • Intent: Check Out Jamstack Book

We’re telling Uniform that anytime we see someone in our Jamstack campaign, we want to show them our book (or other Jamstack-related product or resource).

And finally as one last step to configure our Intent, we need to give Uniform a name that it can use for Analytics as it’s tracking this information.

Click on the Personalization block in the left Composition structure where then on the right we can configure our Personalization including:

  • Analytics tracking name: what Uniform will use to name this section within Analytics, I’m going to use Homepage Promo CTA
  • Match criteria: how we’d like Uniform to present our personalized section, I’m going to select Show matching personalized variations or default variations
  • Number of variations to show: how many to show at one given page view, I’m going to use 1 as I only want a single Call to Action to show
Composition Personalization configuration showing Homepage Promo CTA settings
Configuring Homepage personalization

And with that, we’re ready to go, so we can click the arrow next to the red Save button at the top and select Save and publish!

Now if you try to reload the application, it’s still going to work, however, you won’t be able to load the variations quite yet.

In order to do so, we need to add a bit more code to our app, specifically to give Uniform the ability to hook into the Next.js lifecycle and track the information about our visitor’s state, which we’ll do in the next step.

Step 7: Configuring a Next.js app to use Uniform personalization

After getting our Intent and Composition set up for Personalization, we’re now ready to see it in action. But first, let’s configure our application to be able to work with Personalization!

The way that we currently have our application set up with Uniform, is we’re fetching our Composition data as static data, which then gets passed in as props to React components.

We need to give Uniform a way to track details about our visitor and use that across the entire Next.js lifecycle.

To get started, we need to install some packages from Uniform:

yarn add @uniformdev/optimize-tracker @uniformdev/cli

Next, Uniform needs to have access to an Intent manifest. While we likely can do that within the application, we can instead use the Uniform CLI to download our manifest once and load it into the application as it’s being built.

First, we need to add a new script for building this manifest.

Inside package.json, add the following to your scripts property:

"manifest": "uniform optimize manifest download --output ./data/intent-manifest.json"

Then run the command by running the following in your terminal:

yarn manifest
# or
npm run manifest

This will use your environment variables that we’re already storing locally to make a request to Uniform and grab those details. You can see the file inside of your project at data/intent-manifest.json.

Note: as mentioned earlier, make sure your environment variables are set up and configured inside of .env instead of .env.local otherwise the CLI won’t be able to find your credentials.

Next, we need to wrap our application with Uniform. We can do this by adding our components inside of our custom App file.

Inside _app.js, let’s first import our packages and Intent manifest at the top of the page:

import { UniformTracker } from '@uniformdev/optimize-tracker-react';
import { createDefaultTracker } from '@uniformdev/optimize-tracker-browser';
import intentManifest from '../data/intentManifest.json';

Then we want to create a new tracker instance that we’ll use when wrapping the app.

Below the imports and above the MyApp component, add:

const localTracker = createDefaultTracker({
  intentManifest
});

Finally, let’s replace the entire MyApp Component with the following:

function MyApp({ Component, pageProps }) {
  return (
    <UniformTracker trackerInstance={localTracker}>
      <Component {...pageProps} />
    </UniformTracker>
  );
}

Here, we’re:

  • Wrapping our Next.js Component with the UniformTracker
  • Passing UniformTracker the new tracker that we created along with the scoring prop

And that’s all! So let’s test it.

First, we can make sure that our original experience is working.

Head over to your browser and visit the standard page at http://localhost:3000/ (or whatever port you used), where you should see the default of signing up for a newsletter.

Tip: instead of manually checking, try using the Uniform Optimize Chrome extension which can additionally help you see the “score” you’re given for each Intent based on your Signals.

Next, add the utm_source=newsletter parameter as http://localhost:3000/?utm_source=newsletter as if you were coming from the newsletter. When the page loads, you should now see the alternate experience to follow on social media.

Website showing alternate experience with call to action of following on Twitter
Personalizing for newsletter subscribers via Uniform

Now instead, if you were coming from a link that was part of the Jamstack campaign, where your URL included the parameter utm_campaign=jamstack as http://localhost:3000/?utm_campaign=jamstack, we can see that we get the experience that shows our Jamstack resource!

Website showing alternate experience with call to action of learning about Jamstack book
Personalizing for Jamstack campaign via Uniform

Follow along with the commit!

What else can we do?

This is just a simple example of what we can do with Uniform. Now that we have the base set up, we have a lot of options.

Add more Call to Action variations and Intents

We have the flexibility to add more Intents and add more variations that are targeted to those Intents. Maybe we want to show something different to logged in visitors or wait for them to trigger some kind of event.

There are a lot of options for how we can define our Intents along with the added complexity of stacking Signals on those Intents, from changing how much a Signal increase a score to even decreasing a score.

Add more sources to with Uniform integrations

Uniform has a variety of integrations with popular tools like headless content management and headless commerce. Try hooking up one of your content sources and if you don’t have one yet, now’s a great time to learn about how to use a CMS to manage that content.

Once you do, you can manage the content of your Components with your CMS instead of from inside Uniform, giving a powerful way to manage your content.

Enable server-side or edge-side personalization

To keep things simple, we went with a client-side implementation that renders personalized content as the page loads, but you could alternatively make those personalized changes on a server (SSR) or on the edge if your platform supports it, requiring less work inside the browser.

Want to give it a try? Reach out to Uniform at hi@uniform.dev so they can get your account set up with access!

Try A/B testing

A/B testing is a way to prove with data if one experience is more effective than the other. Using a similar technique to Personalization, we can easily add A/B Testing to our app!

Learn how over on the Uniform docs.