Landing page quickstart
You can use Hypertune to personalize your landing page to each unique visitor using AI.
At a high level, here's how it works:
- 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.Make them configurable in Hypertune.
- 3.Send events to Hypertune to track clicks, sign ups and purchases.
- 4.Define variants of each page element.
- 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.
The schema defines what parts of your page are configurable and what events you want to track.
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
}
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.
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.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.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>
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>
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>
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".
Now Hypertune will automatically learn the best page configuration for each unique visitor to maximize your conversion rate.