Solution Recipe 8: How to create a custom multilingual unsubscribe and preference page in Klaviyo

David
12min read
Developer
March 9, 2022

Solution Recipes are tutorials to achieve specific objectives in Klaviyo. They can also help you master Klaviyo, learn new third-party technologies, and come up with creative ideas. They are written mainly for developers & technically-advanced users.

  • WHAT YOU’LL LEARN: How to use Klaviyo’s hosted pages feature to create customizable, multilingual unsubscribe and preference pages.
  • WHY IT MATTERS: The standard Klaviyo subscribe and preference pages provide easy-to-use preset functionality, but for more advanced use cases, styling requirements or multilingual needs, they might not cover 100% of business/marketing cases.
  • LEVEL OF SOPHISTICATION: High

Introduction

Klaviyo provides an easy-to-use editor for creating unsubscribe and preference pages to use in your email campaigns. For more advanced use cases it may not always be possible to achieve the level of customisation to fit your needs with these tools.

Klaviyo has a feature called “Hosted Pages — these are essentially webpages hosted in your Klaviyo account where you can add your own custom HTML, CSS, Javascript and utilise our Django templating syntax to build your own unsubscribe and preference pages.

Challenge

Customers can have business/marketing use cases where our standard preference/unsubscribe pages do not have the required logic or customisation tools necessary to suit their needs. In these scenarios we can utilise the hosted pages feature in Klaviyo.

An example of this could be to dynamically change the language on an unsubscribe/preference page to match the customers preferred language. While Klaviyo supports multiple languages, the language is set on the account level. As such our standard unsubscribe/preference pages can only be displayed in one language per Klaviyo account.

This solution recipe will walk through how to setup a simple unsubscribe and preference page using Klaviyo’s hosted pages feature. Then it will show you how to add in logic to dynamically change the content depending on a users profile property (in this case country).

Ingredients

  • Intermediate HTML and CSS formatting experience
  • Intermediate level knowledge of the Django templating language
  • A pinch of Javascript

Instructions

Step 1: Enable Hosted Pages in your Klaviyo account

You may not have the Hosted Pages feature enabled in your Klaviyo account. In order to enable it, login to your Klaviyo account and navigate to Account > Settings > Domains and Hosting.

Then click on the “Enable Custom Pages” button as per the screenshot below

Overview of where to enable hosted pages in Klaviyo
Where to enable hosted pages in your Klaviyo account

Note: This setting is only available for an account on a paid plan that has passed account verification.

Once activated, you will see the “Hosted Pages” option appear in your Klaviyo account next to “Preference Pages”.

Step 2A: Create a basic unsubscribe page template

The first step is create an unsubscribe page template by creating a new page and giving it a name of your choice.

Klaviyo will then generate a blank HTML boilerplate template for this page like below:

When this hosted page is used as an unsubscribe link in an email, Klaviyo will automatically add some query parameters that will enable the hosted page to identify the user profile who clicked the link.

This will allow us to fetch and display information for the users profile automatically on the page.

In this example, we will add some HTML and Django syntax that will display the current users name and email address in a form.

Note: I’ve imported the Bootstrap CSS framework for demonstration purposes, but you are free to use your own CSS.

https://medium.com/media/82460bb6c304ef60c816727f0683bc4c

Step 2B: Add the logic to unsubscribe a profile

Now that we have the basic unsubscribe page populating the users details, we need to add some additional hidden fields so that Klaviyo knows what to do when the user submits this form.

In this example, we want Klaviyo to unsubscribe the user when the form is submitted.

In order to do this, we need to add some hidden fields to the form. For unsubscribing they are:

<!-- this hidden field tells Klaviyo what to do when the form is submitted -->
<input type="hidden" name="$unsubscribe" value="true" />
<!-- this hidden field tells Klaviyo where to redirect the user after they unsubscribe (optional) -->
<input type="hidden" name="$unsubscribed_url" value="http://example.com/unsubscribed" />

And that’s it! You now have a simple HTML page that will fetch a profile’s details and then unsubscribe them when they submit the form.

The full HTML for this example is below:

https://medium.com/media/73b1686710e3807cc0a0e73e7a4f38dd

Step 2C: Activate the unsubscribe page for your list

In order for Klaviyo to use your custom hosted page as the unsubscribe page in your emails, you will need to update the “Subscribe & Preference Pages” settings for your list or account.

In this example, I am updating the unsubscribe page to use the custom page I have just created for my list.

Select the “use custom page” option to open the page selector

The last step is to send yourself an email campaign and make sure you use the standard Klaviyo unsubscribe tag 1 {% unsubscribe %} . When you click on it, you should be presented with your custom unsubscribe page.

Note: You will need to send an actual campaign in order to generate a complete unsubscribe link, test sends will not work. Our hosted pages are powered by secure and dynamic URLs which are auto generated at the time of send by Klaviyo. As a result these pages will not have access to personal information as embeds or iframes.

The custom hosted page now works as the unsubscribe page

Step 3A: Create a basic preference page template

Next up we will create our custom preference page, to do this create another hosted page in your Klaviyo account like we did for the unsubscribe page.

Creating another hosted page for the preference page

Similarly to the unsubscribe page, when you use the 1 {% manage_preferences %} syntax in your email, Klaviyo will append a unique query string so that the profile can be identified.

This will allow you to retrieve information specific to that profile (such as their preferences) and display those on the preference page.

We can make use of the Django templating language again to generate the preference page. In this example we are presenting the user with the option to view and edit their email, first name, last name, their favourite breed of dog and how often they would like to receive the newsletter.

I have also added some simple Javascript and jQuery to improve the user experience to allow only one checkbox to be selected at a time.

https://medium.com/media/5527ce28bbe2398256578f1d355affd8

3B) Add the logic to update profile properties

Now that we have our base preference page template, we need to add some extra information so Klaviyo knows which profile properties to update.

The main thing we need to do is include a hidden input field which contains a list of all the profile properties that you wish to update.

For this preference page, it looks like:

<input type="hidden" name="$fields" value="$first_name,$last_name,$email,Favourite Dog,Newsletter Frequency" />

You need to make sure the name attribute of the input fields on your form match up with the names of the profile properties you want to update.

By default when a user submits this preference page they will be redirected to your list’s preferences confirmation page. You can adjust this and redirect a user to another custom hosted page or URL of your choice by including a hidden field like below:

<input type="hidden" name="$updated_profile_url" value="https://example.com/updated_preferences" />

3C) Activate the preference page for your list

Similarly for the unsubscribe page, we now need to adjust the list settings to use this hosted preference page instead of the standard Klaviyo preference page.

Navigate back to the “Subscribe & Preference Pages” setting on your list and now select the hosted page.

Select your custom preference page

Once you have done that, any new campaigns sent to this list which include the 1 {% manage_preferences %} tag in their template will use this new preference page.

Bonus: How to give users the option to unsubscribe from a preference page

You may have noticed in the preference page we also had a link to allow a profile to “Unsubscribe from all emails”.

In order to tell Klaviyo that you want to unsubscribe a profile, you will need to include a hidden field like below:

<input type="hidden" name="$unsubscribe" value="true" />

If this value of this input is set to “true” then Klaviyo will unsubscribe the profile from that list. We will add some Javascript to automatically populate this field when a user clicks on the unsubscribe link and submit the form.

We will add some Javascript to automatically populate this field when a user clicks on the unsubscribe link and submit the form.

$('#unsubscribeLink').on('click',function(e){ e.preventDefault();//stops the page refreshing/jumping $('#unsubscribeFromList').val('true'); //submit the form $('form').submit(); });

Just like for when someone updates their preferences, we can also choose where to redirect a user after they unsubscribe by adding the below field:

<input type="hidden" name="$unsubscribed_url" value="https://example.com/unsubscribed" /> 

The complete code for the page is below:

The complete code for the page is below:

https://medium.com/media/4efad365e8facade28f3b6e41faa993c

Step 4: Making the pages multilingual

At this stage you should have a fully functional custom unsubscribe and preference page. However you may have customers who speak different languages and you want to offer them an unsubscribe/preference page in their preferred language.

If you had separate lists you could re-create these hosted pages for each language and assign them to the relevant list. However this is a time consuming and tedious process. Thankfully there is a better way!

We can make use of the Django templating language to dynamically change the language of our pages.

4A) Fetch the profile property to determine the profiles language

You might have a profile property such as “Language” that you wish to use, but for this example I will be using Klaviyo’s built in “Location.Country” profile property to determine which language to present to the user.

First we fetch the profile property and store it in a variable like below:

{# We assign the profiles country to a variable so we can reference it in the if statement #} {% with personCountry=person|lookup:'Country' %} {% endwith %}

4B) Build the conditional logic

Once we have this, we can then build a series of IF/ELSE statements and create variables to store the translated version of the text we want to use throughout our page.

https://medium.com/media/a626718365338d373e7e81840ae531db

4C) Update the HTML to use the language variables

Now we have all the translated versions of the text stores as variables, we simply need to replace the hardcoded text with these variables.

To do this, we use the {% render_variable variable_name %} template tag. For example to render the variable “unsubscribe_text” we would use the following template tag:

{% render_variable unsubscribe_text %}

One thing to be careful with is to ensure the closing {% endwith %} tag is right at the end of your page, otherwise you won’t be able to access the variable data.

Below you can see the completed HTML for the unsubscribe page, with the language variables used to populate the text.

https://medium.com/media/0fa354d0979ece4e055c31d2df7e81eb

You’ll now see the unsubscribe page will change language depending on the rules you have set automatically.

A Spanish version of the unsubscribe page
A English version of the unsubscribe page

This same approach can also be used to dynamically change the language of your preference page.

Global unsubscribe and preference pages

This guide has covered how you can set each of these hosted pages to a specific list in Klaviyo. You will likely also wish to use these custom pages for your “Global” unsubscribe and preference pages too. These are typically what users see when they unsubscribe from an email sent to a flow or segment.

To update these global pages, navigate to “Preferences Pages” and select “use custom page”

Bonus: Subscribing and unsubscribing from multiple lists

If you are using the list specific unsubscribes setting in Klaviyo, you might want to use lists instead of profile properties to manage your customers preferences.

In this scenario, you simply need to include the list IDs in the hidden fields section in the format like below:

<input type=“hidden” name=“$fields” value=“$list:[LIST_ID1_HERE], $list:[LIST_ID2_HERE], $list:[LIST_ID3_HERE],Favourite Dog,Newsletter Frequency” /> 

and add a corresponding input field to the page with the same name.

<input type=“checkbox” name=“$list:[LIST_ID1_HERE]” value=“true” {% if ‘[LIST_ID1_HERE]’ in person|lookup:‘$lists’ or request.POST|lookup:‘$list:[LIST_ID1_HERE]’ %} checked{% endif %} />

Here is a working example using the preference page from earlier. This will also work for an unsubscribe page (remember to replace the [LIST_ID_X] placeholders as appropriate, for example $list:A1b2C3).

https://medium.com/media/e3e1eb9bc6a160322b39e222cdc86dbb

NB: There is some additional Javascript logic added to uncheck all the list checkbox fields when the “unsubscribe from all” option is chosen. It is not possible to unsubscribe from the list the email was sent to unless the $unsubscribe hidden field is included.

Impact

Klaviyo supports unsubscribe and preference pages out of the box, but sometimes you might want to add additional branding, features and customisation. The Klaviyo Hosted Pages feature lets you leverage all the benefits of HTML/CSS and Javascript and integrate this with your preference/unsubscribe pages to customise them to your requirements.

Learn More!

If you’re interested in learning more about Klaviyo’s developer experience and APIs, please visit developers.klaviyo.com!

David
David Henriquez