This interactive AMP email demonstrates how you can guide users through a step-by-step process using page navigation and AMP state logic—all within an email. No backend or styles required. You can expand on this format for onboarding flows, tutorials, or gated CTA experiences.
We’ll begin with a clean AMP email shell. This sets up the document type, AMP boilerplate, and includes the amp-bind and amp-form scripts that we’ll use later. The CSS will stay minimal for now—just enough to help us orient ourselves visually.
Here’s what our starting structure looks like:
<!doctype html>
<html ⚡4email data-css-strict>
<head>
<meta charset="utf-8">
<style amp4email-boilerplate>body{visibility:hidden}</style>
<script async src="https://cdn.ampproject.org/v0.js"></script>
<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
<style amp-custom>
/* Styles will go here */
</style>
</head>
<body>
<div class="container">
<div class="content-box">
<section class="pages">
<!-- All Pages will go here -->
</section>
</div>
</div>
<footer style=""> <!-- Static footer -->
<a href="https://gregheindel.me">gregheindel.me</a>
</footer>
</body>
</html>
In the next step, we’ll start adding content for the first two pages of our interactive experience.
Before we get into AMP logic, we’ll lay out the structure for Page 1 and Page 2 of the experience. Each page will live inside its own div
so we can later toggle visibility using AMP bindings. For now, everything will render together so we can visually confirm our structure.
Page 1 introduces the checklist. Page 2 lists technical requirements. This is a good point to reinforce how AMP emails can include multi-part experiences without needing additional screens.
Add the following inside the .container
div:
<div id="Page_1">
<div class="inner-content-box">
<div class="center">
<amp-img
aria-describedby=""
src="https://gregheindel.me/img/email/search.png"
width="128"
height="128">
</amp-img>
</div>
<div class="center">
<h1 class="center">How to get approved to send AMP Emails</h1>
<p>
If you want to send AMP emails in production, you need to be approved by Google and configure a few technical and structural requirements. This guide will walk you through each step in a lightweight interactive format.
</p>
<div class="center">
<button
type="button"
class="btn btn-red"
>
Get Started
</button>
</div>
</div>
</div>
</div>
<div id="Page_2">
<div class="inner-content-box">
<h1>
Technical Requirements
</h1>
<p>Before applying for AMP email approval, your domain and email setup need to meet certain technical standards. These ensure your messages are secure and reliably delivered.</p>
<div class="checkboxes">
<label><input type="checkbox" name="domain_verified"> My sending domain is <a href="https://gmail.com/postmaster/">verified in Google Postmaster Tools</a></label><br>
<label><input type="checkbox" name="dkim_setup"> Domain has SPF, DKIM, and DMARC properly configured</label><br>
<label><input type="checkbox" name="https_images"> All my image and hyperlink URLs use HTTPS</label><br>
<label><input type="checkbox" name="plain_fallback"> My AMP email includes a plain text and HTML <a href="https://amp.dev/documentation/guides-and-tutorials/learn/email-spec/amp-email-structure">MIME fallback</a></label>
</div>
<div class="center">
<button
type="button"
class="btn btn-next"
>
NEXT
</button>
</div>
</div>
</div>
You should now see both pages rendered in the email. In the next step, we’ll apply logic to show one page at a time using amp-bind
. This is where the magic begins.
Now that we’ve built our static structure, let’s make it interactive. The goal is to show only one “page” at a time and allow users to navigate between them using buttons.
To do that, we’ll introduce amp-bind, AMP’s simple way of managing state (like variables). We’ll create a state variable called step
, and conditionally show or hide each page depending on its value.
amp-state id="step"
.[hidden]
attribute to each page’s step
value.step
value and navigate forward or back.Place this line directly inside the <body>
tag, before your .container
:
<amp-state id="step">
<script type="application/json"></script>
</amp-state>
This sets our initial view to Page 1.
[hidden]
LogicUpdate each div
which contains the page id
with logic that hides or shows based on the value of step
.
<div [hidden]="step != 1" id="Page_1"> <!-- Here -->
<div class="center">
<h1>How to get approved to send AMP Emails</h1>
<p>If you want to send AMP emails in production, you need to be approved by Google and configure a few technical and structural requirements. This guide walks you through each step in a lightweight, interactive format.</p>
<button class="btn btn-red" on="tap:AMP.setState({ step: 2 })">Get Started</button> <!-- Here -->
</div>
</div>
<div hidden [hidden]="step != 2" id="Page_2"> <!-- Here -->
<div class="inner-content-box">
<h1>
Technical Requirements
</h1>
<p>Before applying for AMP email approval, your domain and email setup need to meet certain technical standards. These ensure your messages are secure and reliably delivered.</p>
<div class="checkboxes">
<label><input type="checkbox" name="domain_verified"> My sending domain is <a href="https://gmail.com/postmaster/">verified in Google Postmaster Tools</a></label><br>
<label><input type="checkbox" name="dkim_setup"> Domain has SPF, DKIM, and DMARC properly configured</label><br>
<label><input type="checkbox" name="https_images"> All my image and hyperlink URLs use HTTPS</label><br>
<label><input type="checkbox" name="plain_fallback"> My AMP email includes a plain text and HTML <a href="https://amp.dev/documentation/guides-and-tutorials/learn/email-spec/amp-email-structure">MIME fallback</a></label>
</div>
<div class="center">
<button
type="button"
class="btn btn-next"
on="tap:AMP.setState({ step: 3 })"> <!-- Here -->
NEXT
</button>
</div>
</div>
</div>
💡 Pro Tip: The[hidden]="step != 1"
syntax hides the element unlessstep
equals 1. This way, we control page visibility through AMP state.
You're now officially controlling your AMP email's view state with a lightweight, client-side state machine!
Next, we’ll complete the sequence by adding two more pages and updating our logic to support navigation through the full flow. These pages cover development requirements and provide a final congratulatory screen with links to submit for AMP approval.
Add the following inside the .container
after Page 2:
<div hidden [hidden]="step !=3">
<div class="inner-content-box">
<h1>Email Development Requirements</h1>
<p>In addition to backend setup, Google expects AMP emails to follow a clean and well-structured development approach. This ensures the messages render correctly and provide a high-quality experience.</p>
<div class="checkboxes">
<label><input type="checkbox" name="amp_validated"> I have validated my AMP email in the <a href="https://playground.amp.dev/"> AMP Playground</a></label><br>
<label><input type="checkbox" name="no_inline_scripts"> The email contains no inline JavaScript or disallowed tags</label><br>
<label><input type="checkbox" name="amp_ready"> The AMP version of the email is production ready</label><br>
</div>
<div class="center">
<button type="button"
class="btn btn-back"
on="tap:AMP.setState({step:2})">
GO BACK
</button>
<button
type="button"
class="btn btn-next"
on="tap:AMP.setState({step:4})">
NEXT
</button>
</div>
</div>
</div>
<!-- PAGE 4 -->
<div hidden [hidden]="step !=4" class="center">
<div class="inner-content-box">
<div>
<div class="center">
<amp-img
class="circle-img"
aria-describedby=""
src="https://gregheindel.me/img/email/reward.png"
width="128"
height="120">
</amp-img>
</div>
<h1>
Congratulations!
</h1>
<p>
Nice! Once you're ready to submit, send your production ready AMP Email to <b>ampforemail.whitelisting@gmail.com</b> and then apply for approval using <a href="https://developers.google.com/workspace/gmail/ampemail/register">Google's AMP Email registration form</a>.
</p>
</div>
<div class="center">
<button type="button"
class="btn btn-back"
on="tap:AMP.setState({step:3})">
GO BACK
</button>
<button
type="button"
class="btn btn-red"
on="tap:AMP.setState({step:1})">FROM THE TOP
</button>
</div>
</div>
</div>
You now have a complete interactive AMP email experience using only AMP HTML, amp-state
, and amp-bind
. In the next step, we’ll explore ways to style and polish the final output.
If you read my guide discussing the flexibility of CSS within AMP Emails then you know we can confidently apply it to our email. Now that the experience is functional, let’s add the complete polished styles we used in the live demo. Paste the following inside your style amp-custom
block
body {
font-family: 'Montserrat', sans-serif;line-height:20pt;
margin:0;
background-color: #FDFBEE;
}
.checkboxes {margin:30px auto;}
.container {
border-radius: 15px;
padding: 0px 0px 25px 0px;
margin: 0px auto;
max-width: 100%;
background-color: #FDFBEE;
}
.inner-content-box {
max-width: 600px;
margin:0 auto;
padding:0 0 20px 0;
}
.btn {
border-radius: 3px;
text-align: center;
padding: 15px 22px;
border: none;
line-height: 22px;
font-size: 18px;
font-weight: bold;
max-width: 300px;
display:inline-block;
}
.btn-red {
background: #FE4F2D ;
color: #FDFBEE;
border:1px solid #fefefe;
}
.btn-next {
background: #063f66 ;
color: #fff;
border:1px solid #fefefe;
}
.btn-back {
background: #fefefe;
color: #666;
border:1px solid #eee;
}
.btn:hover {cursor: pointer;box-shadow: 3px 3px 3px rgba(0,0,0,.2);transition-duration: .5s;}
.center {text-align: center;}
.pages {padding: 0 15px;}
.circle-img {border-radius: 50px;}
a{color:#FE4F2D;}
label{
font-size:1.2rem ;
color:#666;
}
h1 {color:#40a4db;font-size:2rem;line-height:1;}
h3 {color:#063f66 ;font-size:1.5rem;line-height:1;margin:0px 0 35px 0;}
p {color:#666;font-size: 1.2rem;}
.content-box {
text-align: left;
padding: 0px 0px 15px 0px;
max-width: 850px;
margin: 0px auto;
}
footer{
color: #999;
font-family: Open Sans, Helvetica Neue, Helvetica, Arial, sans-serif;
font-size: 12px;
line-height: 150%;
text-align: justify;
text-align: center;
background: #FDFBEE;
}
footer > a {color:#40a4db;}
Congratulations — Now you can create multi-page email with AMP! Try implementing this same logic into a navbar for a website style navigation or to hide and reveal smaller elements like a button when another element is clicked. There are many applications for using amp-bind
this way. Got an idea? Share it with me!
If you are having trouble getting the AMP Email to render properly, you can download the full file here.