In fact, even though our company, Upendo Ventures is well-known for our DNN prowess, many of
our small business clients are currently on Squarespace and unless their needs change,
they're going to stay there. It's the best tool for what they need today. There's a reason
that Squarespace is one of the most popular point-and-click website builder solutions out
there.
There is an overlap though, where Squarespace doesn't appear to be able to do many things
that we'd consider to be more advanced.
Sometimes, a client’s needs begin to branch out, to need to do something the "big boys" may
take for granted, but they otherwise still are perfectly fine staying on Squarespace. An
obvious example for those who already build Squarespace websites would be adding and using
third-party JavaScript libraries or additional fonts. There are what we'd consider "hacks"
to do these more advanced things. One that we're going to highlight in this post is content
personalization.
What is Content Personalization?
Personalized content can allow you to target website visitors in ways that raise the bar
above and beyond any of your competitors. Imagine having the power to display a
different
call-to-action to visitors, based on where they are. For example, what if you
detect that
the visitor is near your location and you offer a discount code for pick-up
only? In that
same scenario, maybe we display a different promo since we know they're not
local. In yet
another, what if we wanted to display a survey, but only to visitors in specific regions?
The possibilities are endless.
Content personalization is a feature that's often reserved for enterprise-level CMSs like
Sitecore or Adobe Experience Manager. However, it doesn't need to be. With a tiny bit of
effort, any website can offer a personalized experience for its visitors. We're going to
show you how, using 51Degrees.
Anyone with a little bit of JavaScript knowledge can implement content personalization in
Squarespace (and other types of sites) using 51Degrees.
51Degrees
51Degrees is known worldwide to be the
fastest and most accurate mobile device detection service available to developers and
website marketers. They power over 1.5 million active implementations around the world and
they are adding up to 200 device definitions every week. It is a no-nonsense decision to use
them for anything mobile like this. They’re available to nearly any platform you can develop
on. If that’s not enough, they’re trusted by brands such as eBay, Seznam, Fiji Airways, and
Home Shopping Network. Luckily, you don't need a brand-name budget to benefit from
51Degrees.
Create & Configure Your 51Degrees Script
If you happen to have used 51Degrees in the past, you should know that the entire getting
started process has been re-imagined. There is now a super-simple wizard to help you get
exactly what you need and nothing you don't, called the 51Degrees Cloud
Configurator.
Since we have a specific example in this article of helping a small business grow its
audience and convert more leads in this time of need, we're going to at a minimum choose a
few of the location properties.
In this case, we're going to help a business named Urbanite Suburbanite display a different
offer to visitors that are local, versus visitors that are not.
SIDE NOTE: Urbanite Suburbanite is the most popular and trusted personal wardrobe
styling service in the San Francisco Bay Area. They've prepared clients for TED talks
and even once styled the original Wonder Woman, Lynda Carter.
There are so many options, by the way. If you're an electronics vendor, you can use this
service to detect if the visitor is on a desktop, tablet, or mobile device. Then, you can
take it a step further to see if their hardware is perhaps outdated and
offer them a coupon to immediately purchase a new device. Mind-blowing!
Grab your pre-populated
properties resource key here.
For this article, we selected the properties highlighted below. The most important ones for
you will be the Location properties.
- Device > Device > IsMobile
- Device > Device > IsTablet
- Device > JavaScript > JavaScriptHardwareProfile
- Operating System > Name > PlatformVendor
- Operating System > Name > PlatformName
- Operating System > Name > PlatformVersion
- Web Browser and Apps > Name > BrowserVendor
- Web Browser and Apps > Name > BrowserName
- Web Browser and Apps > Name > BrowserVersion
- Location > javascript > Javascript
- Location > location > Town
- Location > location > County
- Location > location > Region
- Location > location > State
- Location > location > Country
- Location > location > CountryCode
Now that you have all the properties selected, you can move onto the next screen by clicking
the Details button. Once you've selected the 'Free' option and reviewed and accepted our
Terms and Conditions you can finish the configuration by selecting the Implement button.
(You should, of course, consider entering your contact information and domain name.)
We're going to use the client-side implementation, so be sure to copy the HTML source for
reference later. Otherwise, we're done here.
Adding 51Degrees to Squarespace
To fully implement this, you're going to need to be on the Squarespace Business plan
or higher (as of the time of this writing). This will allow you to add custom scripts
(JavaScript) and CSS (styles) to your site and pages.
We're most likely going to want to add this script to all pages on the site so that we can
offer visitors a promotion no matter where they enter. To manage this setting, you'll want
to refer to Squarespace's documentation on Site-Wide Code Injection.
Once you're viewing the header section in the site-wide code injection editor, you want to
copy and paste the line of code from the HTML example you generated earlier that loads the
51Degrees script from the cloud server. It looks similar to the example below. (FYI - The
file name in the path is unique to your account. Don't share it.) Depending on what you're
doing in there already, you may just want to paste that below the rest of the code that may
be there.
<script async src="https://cloud.51degrees.com/api/v4/YOUR-UNIQUE-FILE-NAME.js"></script>
The rest of the script code is not necessary to copy and paste, but it is a good example of
how to work with the script yourself. The fod object is from 51Degrees and it is your
gateway into fully leveraging their API for your benefit.
SPECIAL NOTE: jQuery is not loaded by Squarespace unless you configure it to do so.
We'll want it for what we're about to do but including it will make it easier to do many
other things in the future. You can do this right now by adding it like you would any
other website, as shown below, loading from CdnJs. You usually want this to be in the top of this setting
field.
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
Save your changes. Technically, we've already integrated 51Degrees into your Squarespace site. Though, it doesn't technically do anything yet... Congratulations!
Create the Content to Personalize
In our example of presenting a different value proposition to local and remote visitors, we can do this many different ways. One way is to completely generate and inject the content via script. To keep this example simple, we're going to do this a different way.
On the given page where you want to display the different call-to-action (CTA), create two different blocks of text with the desired content and imagery. Here you can see that there is a CTA in the header for downloading a white paper and another to use the virtual services option. The Zoom white paper will be shown to "local" visitors, while the other CTA will be shown to visitors that we don't designate as "local."
Luckily for us, Squarespace uses an underlying framework called YUI, and this makes it super-simple for us to find and target any content on the page via CSS and JavaScript based on the ID of the content. You just need to inspect the HTML source to find and note the correct ID attribute.
Note the IDs for the content blocks you want to target for the next and final step.
How to Personalize the Content
Now that we have some content to promote to different people, we can personalize who gets to see which content block. There are several tricks to make this a complete use case. This is the fun part!
Our first step is to prepare the code to wire things up. The snippet below does just that, including the first variable that allows us to not execute the code during the content editing experience. We'll use that first variable to only run our personalization logic in production later.
var $isProduction = (window.location.host == "urbsuburbstyle.com");
var $town = "";
var $state = "";
var $county = "";
var $countryCode = "";
var divLocalVisitor = "#block-yui_3_17_2_1_1601959160530_18648"; // zoom
var divRemoteVisitor = "#block-yui_3_17_2_1_1587141409874_16483"; // virtual
var $divLocal = {};
var $divRemote = {};
By the way, web browsers will hide the "www." in your domain name, if it’s there. If you find that the code is trying to run while you’re in the administration area, you may want to add the "www." to your domain in the snippet above.
For those of you that are not JavaScript novices, you can use the line of code below in the console to check this ahead of time.
console.log(window.location.host);
Next, we're going to use jQuery to hide both CTAs until we're ready to show one of them - but only in production.
jQuery(document).ready(function(){
if ($isProduction){
$divLocal = jQuery(divLocalVisitor);
$divRemote = jQuery(divRemoteVisitor);
if ($divLocal != undefined) {
$divLocal.hide();
}
if ($divRemote != undefined) {
$divRemote.hide();
}
}
});
Now we can run the 51Degrees code to do all the personalization magic we desire. The snippet below is the prescribed way to do this, per the 51Degrees documentation. This event runs after the entire page and its resources have all loaded, while the jQuery event above loads as soon as the page allows it.
window.onload = function() {
/* calling 51Degrees */
fod.complete(function (data) {
/* uncomment the line below to inspect the response from 51Degrees */
/*console.log(data);*/
$town = data.location["town"];
$state = data.location["state"];
$county = data.location["county"];
$countryCode = data.location["countrycode"];
/* only run if the page has the expected elements and is production */
if ($isProduction && $divLocal != undefined && $divRemote != undefined){
if (isVisitorLocal()){
var btnText = jQuery(divLocalVisitor + " a.sqs-block-button-element:first").text();
if ($town === "" || $town == "null"){
// in some rare cases, the town may not be populated
jQuery(divLocalVisitor + " a.sqs-block-button-element:first").html("We love our neighbors\n" + btnText).wrap("<pre/>");
}
else{
jQuery(divLocalVisitor + " a.sqs-block-button-element:first").html("We love our " + $town + " neighbors\n" + btnText).wrap("<pre/>");
}
$divLocal.show();
$divRemote.hide();
}
else {
var btnText = jQuery(divRemoteVisitor + " a.sqs-block-button-element:first").text();
if ($state === "" || $state != "null") {
jQuery(divRemoteVisitor + " a.sqs-block-button-element:first").html("We love our neighbors\n" + btnText).wrap("<pre/>");
}
else{
jQuery(divRemoteVisitor + " a.sqs-block-button-element:first").html("We love our " + $state + " neighbors\n" + btnText).wrap("<pre/>");
}
$divLocal.hide();
$divRemote.show();
}
}
}, 'location'); /* requires user approval to know the location */
}
In the snippet above, an important thing to note is the additional "location" parameter. This will prompt the web browser to request permission from the visitor to know their location. (So, you will want to account for them not giving you permission in your code. The location values will be undefined if they didn't give permission to know their location.)
You may have noticed that the previous snippet makes use of a method named IsVisitorLocal()
. Since the values from 51Degrees were scoped in the earliest snippet, we can easily parse the response to determine if the visitor is local or not. In this example, we're looking for folks in California, but in specific counties.
function isVisitorLocal(){
var isLocal = ($countryCode != undefined && $countryCode == "us" && $state != undefined && $state == "California");
if (!isLocal) {
return false;
}
var localCounties = ["San Francisco County", "San Mateo County", "Santa Clara County", "Alameda County"];
isLocal = (localCounties.indexOf($county) > -1);
return isLocal;
}
If you’re putting together your code step-by-step using the instructions above, do be sure to wrap your code inside of an open <script>
tag and a closing </script>
tag. You’ll see this at the end of the article as well.
If you were to put this all together right now, it would work beautifully. If someone visits the site from a San Francisco Bay Area county, they'll be shown the Zoom white paper CTA. Otherwise, they'll be shown the virtual services CTA. We're going to take this one step further though...
What if we wanted to give them a friendly greeting, based on their location?
When people live near you, it's often proper to think of them and even call them your neighbor. So why not say hello in such a manner? With just a couple more lines of code, we can dynamically update the CTAs to include a friendly greeting.
For local visitors, we're saying that we love our neighbors that live in their town. Everyone else will see a message that we love our neighbors in their respective state. This is a very useful way to catch the eyes of our visitors to further engage with them.
For this to work, the visitor needs to give the script permission to know their location. The 51Degrees script does this for you. Cool, right?
Here is the final result for a local visitor.
Final Personalization Code Snippet for Squarespace
Here is the final snippet for your convenience. We hope you enjoy it! How are you going to personalize your own Squarespace website?
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script async src="https://cloud.51degrees.com/api/v4/REPLACE-ME.js"></script>
<script>
var $isProduction = (window.location.host == "urbsuburbstyle.com");
/* uncomment the line below to inspect the actual domain name */
/*console.log(window.location.host);*/
var $town = "";
var $state = "";
var $county = "";
var $countryCode = "";
var divLocalVisitor = "#block-yui_3_17_2_1_1601959160530_18648"; // zoom
var divRemoteVisitor = "#block-yui_3_17_2_1_1587141409874_16483"; // virtual
var $divLocal = {};
var $divRemote = {};
jQuery(document).ready(function(){
if ($isProduction){
$divLocal = jQuery(divLocalVisitor);
$divRemote = jQuery(divRemoteVisitor);
if ($divLocal != undefined) {
$divLocal.hide();
}
if ($divRemote != undefined) {
$divRemote.hide();
}
}
});
window.onload = function() {
/* calling 51Degrees */
fod.complete(function (data) {
/* uncomment the line below to inspect the response from 51Degrees */
/*console.log(data);*/
$town = data.location["town"];
$state = data.location["state"];
$county = data.location["county"];
$countryCode = data.location["countrycode"];
/* only run if the page has the expected elements and is production */
if ($isProduction && $divLocal != undefined && $divRemote != undefined){
if (isVisitorLocal()){
var btnText = jQuery(divLocalVisitor + " a.sqs-block-button-element:first").text();
if ($town === "" || $town == "null"){
// in some rare cases, the town may not be populated
jQuery(divLocalVisitor + " a.sqs-block-button-element:first").html("We love our neighbors\n" + btnText).wrap("<pre/>");
}
else{
jQuery(divLocalVisitor + " a.sqs-block-button-element:first").html("We love our " + $town + " neighbors\n" + btnText).wrap("<pre/>");
}
$divLocal.show();
$divRemote.hide();
}
else {
var btnText = jQuery(divRemoteVisitor + " a.sqs-block-button-element:first").text();
if ($state === "" || $state != "null") {
jQuery(divRemoteVisitor + " a.sqs-block-button-element:first").html("We love our neighbors\n" + btnText).wrap("<pre/>");
}
else{
jQuery(divRemoteVisitor + " a.sqs-block-button-element:first").html("We love our " + $state + " neighbors\n" + btnText).wrap("<pre/>");
}
$divLocal.hide();
$divRemote.show();
}
}
}, 'location'); /* requires user approval to know the location */
}
function isVisitorLocal(){
var isLocal = ($countryCode != undefined && $countryCode == "us" && $state != undefined && $state == "California");
if (!isLocal) {
return false;
}
var localCounties = ["San Francisco County", "San Mateo County", "Santa Clara County", "Alameda County"];
isLocal = (localCounties.indexOf($county) > -1);
return isLocal;
}
</script>