Hypertune
Search
K

Landing page optimization

Overview

You can use Hypertune to personalize your landing page to each unique visitor with AI.
At a high level, here's how it works:
  1. 1.
    Identify parts of your page that can be personalized like the headline, main image, call-to-action, benefits, social proof, section order, etc.
  2. 2.
    Make them configurable in Hypertune.
  3. 3.
    Send events to Hypertune to track clicks, sign ups and purchases.
  4. 4.
    Define variants of each page element.
  5. 5.
    Create a machine learning loop in Hypertune to learn the best combination of these variants for each unique visitor based on their referral source, location, device type, time of day, day of week, URL parameters, etc.

1. Create a new project

Sign up at app.hypertune.com/register and create a new project.

2. Define your schema

The schema defines what parts of your page are configurable and what events you want to track.
Hypertune uses GraphQL for its schema definition language.
Paste the following starter schema:
type Query {
root(context: Context!): Root!
}
input Context {
user: User!
}
input User {
id: String!
userAgent: UserAgent!
referer: String!
}
type Root {
content: Content!
events: Events!
}
type Content {
headline: String!
imageUrl: String!
benefits: [String!]!
userId: String!
}
type Events {
ctaClick: Void!
}
# User agent types
input UserAgent {
browser: Browser!
device: Device!
engine: Engine!
os: OS!
cpu: CPU!
}
input Browser {
name: String! # e.g. Chrome, Edge, Firefox, Safari
version: String! # dynamic
}
input Device {
type: String! # e.g. mobile, wearable, tablet
vendor: String! # e.g. Apple, Google, HP, HTC, Huawei, Microsoft, Motorola, Nokia, Samsung
model: String! # dynamic
}
input Engine {
name: String! # e.g. Amaya, EdgeHTML, Gecko
version: String! # dynamic
}
input OS {
name: String! # e.g. Android, BlackBerry, Chromium OS, iOS, Mac OS, Windows
version: String! # dynamic
}
input CPU {
architecture: String! # e.g. 68k, amd64, arm, arm64
}

3. Define your logic

Switch to the Logic tab and select the Root field. Click the three dots in the top right of the Root expression and delete it. Then everywhere you see "Select expression", click the first option in the "Logic" submenu (not the "Variables" submenu), and enter a default value for the field, until there are no more errors.
For the userId field, choose the context > user > id variable.
For the ctaClick field, set a Log Event expression with a new event type called "CTA Click" and for the Unit ID, choose context > user > id.
Now you have a basic page configuration with static values for each field.
You'll come back here later to make these values dynamic and personalized with a machine learning loop.
But for now, hit the "Save and activate" button in the navigation bar.

4. Fetch content from your page

Switch to the Preview tab and enter the following query:
query Content(
$userId: String!,
$userAgent: UserAgent!,
$referer: String!
) {
root(
context: {
user: {
id: $userId,
userAgent: $userAgent,
referer: $referer
}
}
) {
content {
headline
imageUrl
benefits
userId
}
}
}
Enter the following query variables:
{
"userId": "#UID#",
"userAgent": "#UA#",
"referer": "#REFERER#"
}
Hypertune uses GraphQL for its query language. In the result panel, you can see just the part of your configuration logic that matches your query.
The #UID# value for the userId variable is a special placeholder that gets replaced with a randomly generated unique ID.
The #UA# placeholder gets replaced with the user agent and the #REFERER# placeholder gets replaced with your landing page URL.
If you're using server-side rendering in Next.js, you'll set the userAgent and referer variables manually when querying Hypertune in getServerSideProps as outlined below.
Switch to the Code Snippets tab in the result panel.
Next.js
HTML / Webflow
Select the JavaScript tab. The snippet defines a function that fetches your content from Hypertune.
Copy the snippet into your code then call the function from your page's getServerSideProps function:
async function getServerSideProps(context) {
const fallbackData = {
root: {
content: {
headline: "Fallback headline",
imageUrl: "https://yourdomain.com/fallback.jpg",
benefits: ["Fallback benefit 1", "Fallback benefit 2"],
userId: ""
},
},
};
const ua = context.req.headers["user-agent"];
const origin = `https://yourdomain.com`;
const referer = `${origin}${context.resolvedUrl}`;
const variables = { userId: "#UID#", userAgent: `#UA:${ua}#`, referer };
try {
const data = await fetchConfigFromHypertune(variables);
return { props: { data } };
} catch (error) {
console.error("Error fetching content from Hypertune:", error);
return { props: { data: fallbackData } };
}
}
If you're using TypeScript, you can use graphql-codegen to get auto-generated types for the returned data.
Select the HTML tab. Copy the snippet and insert it in the <head> of your landing page.

5. Render content on your page

Text

If before you had:
<h1>My headline</h1>
Replace it with:
Next.js
HTML / Webflow
<h1>{props.data.root.content.headline}</h1>
<h1>
<script>
var headline = window.hypertune.get(['root', 'content', 'headline'], 'Fallback headline');
document.write(headline);
</script>
</h1>
This uses the root > content > headline value from Hypertune and falls back to "Fallback headline" in case there's an error.

Images and videos

If before you had:
<img height="300" src="https://yourdomain.com/my_image.jpg" />
Replace it with:
Next.js
HTML / Webflow
<img height="300" src={props.data.root.content.imageUrl} />
<script>
var imageUrl = window.hypertune.get(['root', 'content', 'imageUrl'], 'https://yourdomain.com/fallback.jpg');
document.write('<img height="300" src="' + imageUrl + '" />');
</script>

Lists

If before you had:
<ul>
<li>My Benefit 1</li>
<li>My Benefit 2</li>
<li>My Benefit 3</li>
</ul>
Replace it with:
Next.js
HTML / Webflow
<ul>
{props.data.root.content.benefits.map((benefit) => (
<li key={benefit}>{benefit}</li>
))}
</ul>
<ul>
<script>
var fallbackBenefits = ['Fallback benefit 1', 'Fallback benefit 2'];
var benefits = window.hypertune.get(['root', 'content', 'benefits'], fallbackBenefits);
for (var i = 0; i < benefits.length; ++i) {
document.writeln('<li>' + benefits[i] + '</li>');
}
</script>
</ul>

6. Send events from your page

Switch to the Preview tab and enter the following query:
query Content(
$userId: String!,
$userAgent: UserAgent!,
$referer: String!
) {
root(
context: {
user: {
id: $userId,
userAgent: $userAgent,
referer: $referer
}
}
) {
events {
ctaClick
}
}
}
Enter the following query variables:
{
"userId": "123",
"userAgent": "#UA#",
"referer": "#REFERER#"
}
Switch to the Code Snippets tab and select JavaScript. The snippet defines a function called sendEventsToHypertune that sends a "CTA Click" event to Hypertune.
Next.js
HTML / Webflow
Copy the snippet into your code then call the function from your CTA component's click handler. Set the userId variable to the user ID received in the initial content response from Hypertune:
<button
onClick={() => {
const userId = props.data.root.content.userId;
if (!userId) {
return;
}
sendEventsToHypertune({
userId: userId,
userAgent: "#UA#",
referer: "#REFERER#",
});
}}
>
Sign Up
</button>
Note that since this function is called on the client-side, the #UA# and #REFERER# placeholders will be replaced correctly.
Create a new <script></script> section in the <head> of your page, after the existing Hypertune snippet.
Paste the snippet defining the sendEventsToHypertune function inside. Then immediately after it, define another function called ctaClick which calls sendEventsToHypertune, setting the userId variable to the user ID received in the initial content response from Hypertune. Then call this function from your CTA's click handler:
<script>
function sendEventsToHypertune(variables) {
...
}
function ctaClick() {
var userId = window.hypertune.get(['root', 'content', 'userId'], '');
if (!userId) {
return;
}
sendEventsToHypertune({
userId: userId,
userAgent: "#UA#",
referer: "#REFERER#"
});
}
</script>
...
<button onclick="ctaClick();">Sign Up</button>

7. Create a machine learning loop

Switch to the Logic tab in the Hypertune UI.
Remove the Text expression from the headline field.
Replace it with a Test / ML expression.
Select the split dropdown and create a new split.
Change the split type from "Test" to "ML Loop".
Name the split "Landing Page ML Loop".
Set the Goal Event Type to "CTA Click".
Click the "+ New Dimension" button twice so there are 3 dimensions in total. We'll have one dimension for our headline variations, one for the image URL variations and one for the benefits variations.
Switch to the 1st dimension and name it "Headline".
Click "+ New Arm" until the dimension has 3 arms. Name them "Headline A", "Headline B" and "Headline C".
Switch to the 2nd dimension and name it "Image URL". Create 3 arms called "Image URL A", "Image URL B" and "Image URL C".
Switch to the 3rd dimension and name it "Benefits". Create 3 arms called "Benefits A", "Benefits B" and "Benefits C".
Click "Save" to close the split modal.
Now in the dimension dropdown of the Test / ML expression, select the "Headline" dimension.
Set "Unit ID" to context > user > id and set the "Headline A", "Headline B" and "Headline C" arms to your headline variations.
Now do the same for the imageUrl field. Replace the Text expression with a Test / ML expression. Select "Landing Page ML Loop" in the split dropdown and then "Image URL" in the dimension dropdown. Set "Unit ID" to context > user > id and then set the arms to your image URL variations.
Now do the same for the benefits field.
Finally, hit "Save and activate".

That's it

Now Hypertune will automatically learn the best page configuration for each unique visitor to maximize your conversion rate.