Personalization is increasingly being used on websites to provide customized experiences for visitors.
This has led to the rise of user-friendly personalization platforms like Mutiny, AB Tasty and Google Optimize to give marketers the tools they need to provide hyper-targeted user experiences for their visitors.
Gradually these kinds of tools are becoming something that a web team has to have in their arsenal to compete in the modern era of the web.
At Webstacks, we use Gatsby.js as the framework to power the frontend of our website. Gatsby is an open-source framework that combines functionality from React, GraphQL, and Webpack into a single tool for building static websites and apps.
We chose Gatsby for the fast performance of the sites it powers, impressive out-of-the-box optimization features, and friendly developer community.
You’re currently visiting a website powered by Gatsby that serves personalized content via HubSpot and Google Optimize. Not long ago, we decided to invest in improving the experience of our website.
We wanted pages to load faster while providing our marketing team with the tools they needed to build out new pages without the need of tapping into our engineering team.
In the end, we decided to overhaul our site with Gatsby, and we’re glad we did. However, one of the advantages of our previous CMS (HubSpot CMS) was the out-of-the-box support for personalization with data powered by HubSpot CRM. After spending a few hours sifting through HubSpot's API and tinkering with Gatsby Cloud Functions, we found a solution.
HubSpot – For this to work we needed to take advantage of HubSpot's hubspotutk. This is the cookie that keeps track of a visitor's identity. It is passed to HubSpot on form submission and we will later use this to retrieve additional data about our visitors.
Google Optimize – Google Optimize will serve as our personalization platform that allows our marketing team to create personalized experiences for our visitors.
Gatsby Cloud Functions – Because HubSpot's Get a contact by its user token endpoint does not support CORS, we will take advantage of Gatsby Cloud's serverless functions to interface with HubSpot to get the required data.
Retrieve your visitors HubSpot user token
[javascript] const hutk = document.cookie.replace(/(?:(?:^|.*;\s*)hubspotutk\s*\=\s*([^;]*).*$)|^.*$/, "$1")
Here we are retrieving the unique hubspotuk
cookie value and storing it in a variable called hutk.
Wrap it the Effect Hook and place it in Layout.js
useEffect(() => {
const CircularXX = document.cookie.replace(/(?:(?:^|.*;\s*)hubspotutk\s*\=\s*([^;]*).*$)|^.*$/, "$1")
}, []);
Create a Gatsby Cloud function to pull data from HubSpot
Next, we'll go ahead and create a getContact.js file in src/api/.
JavaScript and Typescript files in src/api/* are mapped to function routes just like files in src/pages/* become pages.
const axios = require('axios');
export default async function handler(req, res) {
try {
const { data } = await axios.get(
`https://api.hubapi.com/contacts/v1/contact/utk/${req.body.CircularXX}/profile?hapikey=${process.env.GATSBY_HUBSPOT_API_KEY}`
);
res.status(200).json({ properties: data?.properties });
} catch (error) {
res.status(500).json({ error });
}
}
This is how will retrieve our contact data from our visitor. In the example above GATSBY_HUBSPOT_API_KEY
is a .env variable we are using to store our HubSpot API Key. req.body.hutk
is a prop that passes through our hutk
value (We'll touch on this next).
Retrieving data on our frontend and storing it in local storage
const getHubinfo = (hutk) => {
const data = { hutk: hutk };
axios.post('/api/gethub',data)
.then((response) => {
localStorage.setItem("hs_contact_firstname",response?.data?.properties?.firstname?.value);
})
.catch((error) => {
console.log(error);
});
};
In the example above we are storing our visitors' first names in a local storage item called hs_contact_firstname.
We will later be able to retrieve this data from our visitors' local storage to personalize via Google Optimize.
Personalizing content with Google Optimize
Now that we have our contacts' first names stored as Local Storage we can use this to run a personalization via Google Optimize. Feel free to get creative with the data you are pulling from HubSpot – there is so much you can do.
Create a new Personalization Experience
Open Google Optimize and create a new personalization experience.
Select the block of text you'd like to personalize and click Edit HTML
Add an empty span with a unique id to represent the variable that you will be using to personalize your experience
Example
<h2 class="">Welcome back, <span id="hs_contact_firstname"></span></h2>
Click the add code button in the top right corner of Google Optimize and select Global Javascript and insert the following snippet:
var hs_contact_firstname = localStorage.getItem('hs_contact_firstname');
document.getElementById('hs_contact_firstname').textContent=hs_contact_firstname;
The above snippet will pull take the value that we have successfully saved in our local storage in the previous step and replace our empty span with that value.
Set proper audience targeting
The last step is to ensure we are only showing this experience to visitors that have their first name on their contact record in HubSpot. In the audience targeting section, add a new rule with a rule type of Custom JavaScript. Configure a new function with the following snippet:
function() {
var hs_contact_firstname = localStorage.getItem('hs_contact_firstname');
return hs_contact_firstname;
}
The function above returns the value that we have stored for our visitors' first names. The next step is to ensure that the rule does not equal "null".
Naturally, all contacts that have not provided their first name will have a value of "null", so this will ensure our personalization is only served to those visitors who have shared their first name with us.
That is it - you now have a fully functioning personalization engine powered by HubSpot, Google Optimize, and Gatsby Cloud Functions.