How to Create a Lead Capture Page
Go to Pages

Click "Create"
Set "Route" to the URL you want this page to use.
e.g. https://username.engram.sh/lead-capture

Click "Create" in the modal
By default, you will see the "Preview" tab.
The page is completely empty and so you'll see a white page.
The "Open External" icon in the top right opens the page in a new tab so you can see exactly how it looks for viewers.

AI Coding Assistant
The sidebar on the right side of the screen is an early prototype to demonstrate how things could work in the future.
It is still buggy, but has it's uses. To demonstrate it, we will use it for the first couple of requests.
After this I will provide a couple of other recommendations for something that may work better for now until this is fully functional.
Create the First Iteration of the Page
Use the coding assistant to create the first version of the page.
There are quite a few specifics around how the page needs to be created. For now I've included these in the prompt to make sure it generates something that works.
TODO: In the future, the agent will know how to do this without being explicitly told each time.
Everything below "- - -" in the prompt below won't be needed in the future.
While you can make several prompts in succession, it is usually more effective (and cheaper) to combine all your requests in one. Especially when creating the first version of the page.
Copy this prompt below, paste it into the input in the bottom right of the Edit Page view, and then press enter.
Create a page that requests the users first name, last name, phone number, and email.
Add a placeholder image at the top in a circle
Add text "Get Notified about events, merch, and drops"
Disable the Submit button until all fields are entered
- - -
Use libphonenumber-js from CDN to format number using AsYouType
Set the form id to "lead"
Set data-maps-to attribute on each input to "Contact First Name", "Contact Last Name", "Contact Phone, and "Contact Email"
Your design and HTML may come out different. If you like to skip the AI step, you can copy the HTML below and paste inside the Code tab.
HTML Code
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>get notified</title>
<script src="https://unpkg.com/libphonenumber-js@1.11.4/bundle/libphonenumber-js.min.js"></script>
<style>
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background-color: var(--background, #f5f5f5);
color: var(--foreground, #111);
font-family: var(--body-font, sans-serif);
padding: 2rem 1rem;
}
.card {
background: #fff;
border-radius: 1.25rem;
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.1);
padding: 2.5rem 2rem;
width: 100%;
max-width: 440px;
display: flex;
flex-direction: column;
align-items: center;
gap: 1.5rem;
}
.avatar-wrapper {
width: 110px;
height: 110px;
border-radius: 50%;
overflow: hidden;
border: 3px solid var(--primary, #6c63ff);
flex-shrink: 0;
}
.avatar-wrapper img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.headline {
font-family: var(--heading-font, inherit);
color: var(--heading-color, var(--foreground, #111));
font-size: 1.3rem;
font-weight: 700;
text-align: center;
line-height: 1.3;
}
form {
width: 100%;
display: flex;
flex-direction: column;
gap: 1rem;
}
.field-row {
display: flex;
gap: 0.75rem;
}
.field {
display: flex;
flex-direction: column;
gap: 0.35rem;
flex: 1;
}
label {
font-size: 0.8rem;
font-weight: 600;
color: var(--foreground, #333);
text-transform: lowercase;
letter-spacing: 0.02em;
}
input {
width: 100%;
padding: 0.65rem 0.85rem;
border: 1.5px solid #ddd;
border-radius: 0.6rem;
font-size: 0.95rem;
font-family: var(--body-font, sans-serif);
color: var(--foreground, #111);
background: #fafafa;
transition: border-color 0.2s, box-shadow 0.2s;
outline: none;
}
input:focus {
border-color: var(--primary, #6c63ff);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary, #6c63ff) 15%, transparent);
background: #fff;
}
input::placeholder {
color: #aaa;
}
button[type="submit"] {
margin-top: 0.25rem;
padding: 0.75rem 1rem;
background-color: var(--primary, #6c63ff);
color: var(--primary-foreground, #fff);
border: none;
border-radius: 0.6rem;
font-size: 1rem;
font-weight: 700;
font-family: var(--body-font, sans-serif);
cursor: pointer;
transition: opacity 0.2s, transform 0.1s;
width: 100%;
text-transform: lowercase;
letter-spacing: 0.03em;
}
button[type="submit"]:not(:disabled):hover {
opacity: 0.88;
}
button[type="submit"]:not(:disabled):active {
transform: scale(0.98);
}
button[type="submit"]:disabled {
opacity: 0.4;
cursor: not-allowed;
}
</style>
</head>
<body>
<div class="card">
<div class="avatar-wrapper">
<img
src="https://placehold.co/110x110"
alt="placeholder profile image"
/>
</div>
<p class="headline">get notified about events, merch, and drops</p>
<form id="lead" novalidate>
<div class="field-row">
<div class="field">
<label for="first-name">first name</label>
<input
type="text"
id="first-name"
name="first-name"
placeholder="jane"
autocomplete="given-name"
data-maps-to="Contact First Name"
required
/>
</div>
<div class="field">
<label for="last-name">last name</label>
<input
type="text"
id="last-name"
name="last-name"
placeholder="doe"
autocomplete="family-name"
data-maps-to="Contact Last Name"
required
/>
</div>
</div>
<div class="field">
<label for="phone">phone number</label>
<input
type="tel"
id="phone"
name="phone"
placeholder="(555) 000-0000"
autocomplete="tel"
data-maps-to="Contact Phone"
required
/>
</div>
<div class="field">
<label for="email">email</label>
<input
type="email"
id="email"
name="email"
placeholder="jane@example.com"
autocomplete="email"
data-maps-to="Contact Email"
required
/>
</div>
<button type="submit" id="submit-btn" disabled>notify me</button>
</form>
</div>
<script>
(function () {
const form = document.getElementById('lead');
const submitBtn = document.getElementById('submit-btn');
const phoneInput = document.getElementById('phone');
const inputs = form.querySelectorAll('input[required]');
// as-you-type phone formatter
const formatter = new libphonenumber.AsYouType('US');
phoneInput.addEventListener('input', function (e) {
const raw = e.target.value.replace(/\D/g, '');
formatter.reset();
const formatted = formatter.input(raw);
e.target.value = formatted;
checkValidity();
});
function checkValidity() {
const allFilled = Array.from(inputs).every(function (input) {
return input.value.trim() !== '';
});
submitBtn.disabled = !allFilled;
}
inputs.forEach(function (input) {
if (input.id !== 'phone') {
input.addEventListener('input', checkValidity);
}
});
form.addEventListener('submit', function (e) {
e.preventDefault();
// submission logic can be added here
});
})();
</script>
</body>
</html>Add an Image
Files need to be uploaded separately before they can be used.
Go to Files
Upload a profile image that will be used for the top of this lead capture page.

Click Copy URL

Head back to the page you are editing
Change the "Full" dropdown to "Diff"

Full tells the agent to rewrite the entire HTML file. This is good when there are lots of changes, but is slow and expensive when only making small changes.
Diff tells the agent to only return what has specifically changed. It will be faster and cheaper for small iterative changes.
In the future, it will likely auto-detect between the two, but for now it is up to you. When in doubt (or if having issues) use full as diff sometimes fails.
Enter the following prompt into the chat:
Update the image with url:and then paste (ctrl + v) the URL you just copied
The preview should automatically reload with the changes.

Test the Page
(Ignore the color changes, I had custom colors set up in the screenshot above. Yours should actually look like what is shown below)


View Responses
Head to the "Responses" tab under the edit page.
Here you will see all the responses that have been made, which form id was submitted (in case there were multiple forms), and what information was entered.

Create a Contact on Submit
By default, pages do not create a contact in the system.
This ensures you can use this to collect any kind of information that you may not want automatically added to your main contact database.
Head to the "Settings" tab

Type "lead" into the Form ID input.

Click "Add form"

Click "Add action..." dropdown
Select "Create Lead"

Click "Save" button
TODO: The save button is in a really weird place
Now re-submit the form
Head to "Responses" tab
You will now see that the first column shows a link icon. This links to the contact that this submission is attached to.
If a contact didn't already exist, a new one was created.
If one already existed, this new submission is attached to the existing contact to avoid duplicate contacts.
