Cookie Preference Centre

These cookies are required for the site to work and therefore can't be removed: Grav session cookie (necessary, cannot be removed).

Third-party tools used to monitor performance and improve the user experience: Google Analytics, Google Optimize.

Widgets added to the site to provide additional features: LinkedIn, Bitrix24.

Are you ok with optional cookies? They let us give you a better experience and improve the content we publish on this site.

Your cookie settings have been updated

tools-icon Free CRO Tools

Tools & processes I use to increase my clients' bottom lines. Get free access!

or
I respect your privacy You'll be required to confirm your email address, thereby confirming the request truly came from you. I will neither spam you nor share your email with anyone. I thank you for placing your trust in me.

I provide growth strategy and execution, with thorough research and high velocity testing to get traction fast.

I only work with a few clients at a time, in 3 to 6 months engagements. I charge premium rates (2500-5000โ‚ฌ/mo) and deliver premium results.

Can you apply for my services?

Yes, if you are a 7-figure (and up) digital business (eCommerce, SaaS, digital services, online communities).

How to apply?

You start by ordering a (paid) Growth Diagnostic:


1500 โ‚ฌ

33% off
Growth Diagnostic at

only 990 โ‚ฌ

Building dynamic landing pages with Google Optimize

Reading time: 9 minutes, 1 second
Building dynamic landing pages with Google Optimize

Custom landing pages are the key to conversion. Continuity between the traffic source and the first page of the visit is critical to get visitors to stay on the site and browse to other pages.

You can't expect your landing page to convert well if the content is not specifically tailored to the target audience. For example if you click on an iPhone ad, you expect to see iPhones, and not smartphones from every brand out there.

If your landing pages have high bounce rates, chances are the content is not targeted enough. This often means you need to segment the traffic and build dedicated landing pages for each segment.

It quickly becomes very impractical however, when you have to build and maintain 1 landing page for every ad, influencer campaign, organic keyword. So what can you do?

You build a dynamic landing page of course!

What's a dynamic landing page?

It is a landing page whose content changes based on parameters. One single page can be tailored to provide relevant content for many specific scenarios.

It's much easier and faster to insert dynamic elements into a standard landing page than building a new landing page every time. Let me show you how with a simple example.

Here are a few examples of how you can use dynamic landing pages to boost conversions:

  • Influencer traffic: display the name and avatar of the influencer at the top of the landing page, for example in a header bar. The format "Influencer XYZ recommends you try PRODUCT" works particularly well in my experience.
  • Organic traffic: display shipping fees or free shipping thresholds applicable based on geolocation. "Free domestic shipping" is very often a conversion-killer for international traffic.
  • Ads traffic: display the first headline of the ad or the search query at the top of the landing page. If the visitor clicks based on your ad and see the same message upon landing, they will stay because there is continuity between the ad and the landing page.
  • Email or CRM traffic: display purchase history or recent browsing activity. Visitors already familiar with your brand don't need the same content as new visitors.

Let's get started (-:

This tutorial requires some basic understanding of javascript.

Step 1. Add query parameters to your landing page URL

The first step is to add query parameters to the URL of your landing page. Feel free to use UTM parameters (very useful to later segment data in Google Analytics) or to create your own from scratch:

https://yourpage.com/?utm_term=term
https://yourpage.com/?parameter=value
https://yourpage.com/?param1=value1&param2=value2

Query parameters can represent anything that might be useful to deliver the right message to the right person; for example: ad campaign, ad group, keyword, search query, gender, age, product, service, location, etc.

You don't always need to use query parameters to target visitor segments. For example you can identify the country of origin directly or use cookies or CRM integrations to set up the data flows you need to segment your landing pages. But any user or behaviour data needs to be passed along via query parameters. For the sake of this example I'll keep things simple and rely solely on query parameters.

I will use these parameters: ?segment=one&offer=Buy%202%20Get%201%20Free&page=intro. As you can see I am using %20 to encode spaces into the URL.

You'll need to update the links pointing to your landing page accordingly.

Step 2. Read the dynamic parameters

Here is a JS function that reads query parameters:

function getParameters(name) {
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
var results = regex.exec(location.search);
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
};

To get the value of a query parameter you can then call the function this way:

var segment = getParameters('segment');
console.log(segment); // Returns "one"
var offer = getParameters('offer');
console.log(offer); // Returns "Buy 2 Get 1 Free"
var page = getParameters('page');
console.log(page); // Returns "intro"

Step 3. Define what content to display based on parameters

You can create rules in the code of the landing page (manual setup), or scrape the data automatically, or a mix of both approaches. It all depends on what data is available to you and what content you need to display on the landing page.

Manual setup: you configure every scenario

There are several ways of doing this. A simple if/else logic would work very well here, but I personally prefer using switch statements for clarity. Up to you though!

The following piece of code assigns a string of text and an image based on the segment identified via the segment query parameter:

if(segment != '') {
    switch(segment) {
        case 'one':
           text = "This is segment ONE";
           image = "segment-one.jpg";
           break;
        case 'two':
           text = "This is segment TWO";
           image = "segment-two.jpg";
           break;
        case 'three':
           text = "This is segment THREE";
           image = "segment-three.jpg";
           break;
        default:
           text = "No segment identified";
           image = "segment-none.jpg";
    }
}

Automated setup: scrape data from your site

There are many limitations to such a setup but one huge avantage: you can have many content variations without configuring every single variant!

It is very useful when you want to display product or service data: if you have a standard landing page, you can use such a configuration to grab title, description, price, etc. from your own pages. This also means you won't have to update your landing page when updating products or services because it grabs the live data.

The following piece of code grabs the title of the page identified via the page query parameter:

if(page != '') {
    var request = new XMLHttpRequest();
    request.open('GET', '/course/'+page, true);
    request.onload = function() {
        if(request.status >= 200 && request.status < 400) {
            var resp = request.responseText;
            var parser = new DOMParser();
            var data = parser.parseFromString(resp,"text/html");
            var title = data.querySelector('h1');
        }
    };
    request.onerror = function() {};
    request.send();
}

The line request.open('GET', '/course/'+page, true); defines what page we take the data from. In this case, we will take the data from the page /course/intro because the query parameter page is set to intro.

Step 4. Display dynamic content

Let's display the 3 parameters used in this tutorial.

Output query parameter value

<span id="offer-output"></span>
<script>
    var offerOutput = document.getElementById('offer-output');
    offerOutput.innerHTML = offer; // The variable "offer" was defined in step 2
</script>

You can test this by appending ?offer=Buy%202%20Get%201%20Free to the URL of this page:

Offer: No offer

Output scraped data

<span id="page-output"></span>
<script>
    var pageOutput = document.getElementById('page-output');
    // To put inside the http request:
    pageOutput.innerHTML = title.innerHTML;
</script>

You can test this by appending ?page=intro to the URL of this page:

Page: No page

Output custom data

<p id="segment-text-output"><img id="segment-image-output" src="" /></p>
<script>
    var segmentImageOutput = document.getElementById('segment-image-output');
    var segmentTextOutput = document.getElementById('segment-text-output');
</script>

You can test this by appending ?segment=one to the URL of this page:

Segment: No segment

Step 5. Putting it all together in Google Optimize

Create a new campaign

  1. Create a new campaign in your Google Optimize container.
  2. Give a name to the campaign.
  3. Enter the URL of the landing page.
  4. Select "personalization" or "A/B test" as campaign type. Choose "A/B test" if you wish to measure the performance of your dynamic landing page vs. standard content (highly recommended).

Add site changes

Add the JS code as global javascript in the Google Optimize editor. Here is the full code:

function getParameters(name) {
    name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
    var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
    var results = regex.exec(location.search);
    return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
};
var segment = getParameters('segment');
var offer = getParameters('offer');
var page = getParameters('page');
if(segment != '') {
    var segmentImageOutput = document.getElementById('segment-image-output');
    var segmentTextOutput = document.getElementById('segment-text-output');
    switch(segment) {
        case 'one':
           text = "This is segment ONE";
           image = "segment-one.jpg";
           break;
        case 'two':
           text = "This is segment TWO";
           image = "segment-two.jpg";
           break;
        case 'three':
           text = "This is segment THREE";
           image = "segment-three.jpg";
           break;
        default:
           text = "No segment identified";
           image = "segment-none.jpg";
    }
    segmentTextOutput.innerHTML = text;
    segmentImageOutput.src = window.location.pathname + '/' + image;
}
if(offer != '') {
    var offerOutput = document.getElementById('offer-output');
    offerOutput.innerHTML = offer;
}
if(page != '') {
    var pageOutput = document.getElementById('page-output');
    var request = new XMLHttpRequest();
    request.open('GET', '/course/'+page, true);
    request.onload = function() {
        if(request.status >= 200 && request.status < 400) {
            var resp = request.responseText;
            var parser = new DOMParser();
            var data = parser.parseFromString(resp,"text/html");
            var title = data.querySelector('h1');
            pageOutput.innerHTML = title.innerHTML;
        }
    };
    request.onerror = function() {};
    request.send();
}

Add HTML and CSS changes as needed. Although you can do without you might want to add IDs in the code of the page to identify dynamic elements.

As a starting point you might want to append the following HTML to the page:

<ul class="dynamic-parameters">
    <li>
        <strong>Offer:</strong>
        <span id="offer-output">No offer</span>
    </li>
    <li>
        <strong>Page:</strong>
        <span id="page-output">No page</span>
    </li>
    <li>
        <strong>Segment:</strong>
        <img id="segment-image-output" src="" />
        <span id="segment-text-output">No segment</span>
    </li>
</ul>

And set the following CSS as global CSS in the Google Optimize editor:

.dynamic-parameters {
    list-style: disc;
}
#segment-image-output {
    display: inline;
    width: 16px;
    position: relative;
    top: 2px;
    margin: 0 5px;
    box-shadow: none;
}

Set up targeting options

Make sure URL targeting is set to URL matches and points to the URL of your landing page without query parameters.

You may also want to only trigger this campaign if the query parameters used to display dynamic elements are present in the URL. You can do so with Audience targeting > Advanced > Query parameter.

You're all set (-:


Personalization very often leads to higher conversion rates. But to achieve big conversion uplifts you must pick parameters that are relevant to the visitor.

So once you've successfully created a Google Optimize campaign as described in this tutorial, make sure you carefully select dynamic elements for your site and start building your own dynamic landing page.

Happy Optimizing (-:

Photo by Halacious on Unsplash