Interactive email template

Calendar booking form

Book meeting slots from the inbox with date selection and host context.

Use an in-email booking surface to cut friction between interest and call setup.

Inbox preview

Static HTML rendering of the email body. Use it to check the layout before sending the live AMP version to a test inbox.

Gmail · Primary

Mailneo demo <hello@mailneo.co>

10:42 AM (2 min ago)

Calendar booking form

to me · interactive email

Interactive preview

Book a strategy call

Pick day, slot, and agenda in one booking form.

  • Strong for demo scheduling.
  • Supports pre-call context capture.
  • Final availability checks still run on backend calendars.
Book call

code snippets

<!doctype html>
<html amp4email>
  <head>
    <meta charset="utf-8" />
    <script async src="https://cdn.ampproject.org/v0.js"></script>
    <script async custom-element="amp-form" src="https://cdn.ampproject.org/v0/amp-form-0.1.js"></script>
    <script async custom-element="amp-selector" src="https://cdn.ampproject.org/v0/amp-selector-0.1.js"></script>
    <script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
    <script async custom-element="amp-list" src="https://cdn.ampproject.org/v0/amp-list-0.1.js"></script>
    <script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.2.js"></script>
    <style amp4email-boilerplate>
      body {
        visibility: hidden;
      }
    </style>
    <style amp-custom>

  body {
    margin: 0;
    padding: 20px;
    background: #f8fafc;
    font-family: Arial, Helvetica, sans-serif;
    color: #1f2937;
  }
  .email-card {
    max-width: 640px;
    margin: 0 auto;
    background: #ffffff;
    border: 1px solid #e2e8f0;
    border-radius: 14px;
    overflow: hidden;
  }
  .header {
    background: #fff7ed;
    border-bottom: 1px solid #fed7aa;
    padding: 20px 24px;
  }
  .header h1 {
    margin: 0;
    font-size: 22px;
    line-height: 1.3;
    color: #9a3412;
  }
  .header p {
    margin: 8px 0 0;
    font-size: 14px;
    line-height: 1.5;
    color: #7c2d12;
  }
  .section {
    padding: 20px 24px;
  }
  label {
    display: block;
    margin: 0 0 6px;
    font-size: 13px;
    line-height: 18px;
    font-weight: 700;
    color: #334155;
  }
  input,
  textarea,
  select {
    width: 100%;
    box-sizing: border-box;
    margin: 0 0 12px;
    padding: 10px 12px;
    border: 1px solid #cbd5e1;
    border-radius: 8px;
    font-size: 14px;
    color: #1f2937;
    background: #ffffff;
  }
  textarea {
    min-height: 90px;
    resize: vertical;
  }
  .inline-checkbox {
    width: auto;
    margin: 0 8px 0 0;
    vertical-align: middle;
  }
  .button {
    display: inline-block;
    border: 0;
    border-radius: 8px;
    background: #f97316;
    color: #ffffff;
    text-decoration: none;
    font-size: 14px;
    font-weight: 700;
    line-height: 1;
    padding: 12px 16px;
    cursor: pointer;
  }
  .button.alt {
    background: #ea580c;
  }
  .button.ghost {
    background: #ffffff;
    color: #9a3412;
    border: 1px solid #fdba74;
  }
  .muted {
    margin: 10px 0 0;
    font-size: 12px;
    line-height: 18px;
    color: #64748b;
  }
  .chip {
    display: inline-block;
    border: 1px solid #fdba74;
    border-radius: 999px;
    padding: 8px 12px;
    margin: 0 8px 8px 0;
    font-size: 13px;
    line-height: 1;
    color: #9a3412;
    background: #fff7ed;
  }
  amp-selector [option][selected] {
    background: #f97316;
    color: #ffffff;
    border-color: #f97316;
  }
  .score-grid [option] {
    min-width: 40px;
    text-align: center;
  }
  .step-nav {
    margin-bottom: 14px;
  }
  .step-pill {
    display: inline-block;
    width: 28px;
    height: 28px;
    border-radius: 999px;
    border: 1px solid #cbd5e1;
    color: #475569;
    text-align: center;
    line-height: 28px;
    font-size: 12px;
    margin-right: 8px;
  }
  .step-pill.active {
    border-color: #f97316;
    background: #f97316;
    color: #ffffff;
  }
  .note-box {
    border: 1px dashed #fdba74;
    border-radius: 10px;
    padding: 10px 12px;
    margin: 12px 0;
    background: #fff7ed;
    font-size: 13px;
    line-height: 1.5;
    color: #7c2d12;
  }
  .session-card {
    border: 1px solid #e2e8f0;
    border-radius: 10px;
    padding: 14px;
    background: #ffffff;
  }


    </style>
    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1" />
    <title>Calendar booking</title>
  </head>
  <body>
    <div class="email-card">
      <amp-state id="bookingState">
        <script type="application/json">
          {"day": "jun-20", "slot": "10:00-am"}
        </script>
      </amp-state>
      <div class="header">
        <h1>Book your strategy session</h1>
        <p>Select a day and time that works for your team.</p>
      </div>
      <div class="section">
        <amp-list
          width="auto"
          height="72"
          layout="fixed-height"
          src="https://example.com/api/hosts"
        >
          <template type="amp-mustache">
            <div class="note-box">Host: {{name}} | Region: {{region}} | Next free slot: {{next_slot}}</div>
          </template>
        </amp-list>

        <form method="post" action-xhr="https://example.com/api/calendar-booking" target="_top">
          <label>Choose day</label>
          <amp-selector
            layout="container"
            on="select:AMP.setState({bookingState: {day: event.targetOption, slot: bookingState.slot}})"
          >
            <div option="jun-20" selected class="chip">Jun 20</div>
            <div option="jun-21" class="chip">Jun 21</div>
            <div option="jun-22" class="chip">Jun 22</div>
          </amp-selector>

          <label>Choose slot</label>
          <amp-selector
            layout="container"
            on="select:AMP.setState({bookingState: {day: bookingState.day, slot: event.targetOption}})"
          >
            <div option="10:00-am" selected class="chip">10:00 AM</div>
            <div option="1:00-pm" class="chip">1:00 PM</div>
            <div option="4:00-pm" class="chip">4:00 PM</div>
          </amp-selector>

          <input type="hidden" name="day" [value]="bookingState.day" />
          <input type="hidden" name="slot" [value]="bookingState.slot" />

          <label for="cb-agenda">Agenda (optional)</label>
          <textarea id="cb-agenda" name="agenda"></textarea>

          <button class="button" type="submit">Confirm booking</button>
        </form>
      </div>
    </div>
  </body>
</html>

AMP components used

amp-formamp-selectoramp-bindamp-listamp-mustache

use cases

  • Demo scheduling

    Move prospects from campaign click to meeting booked.

    Industry: SaaS

  • Consulting sessions

    Capture call agenda and route to the right consultant.

    Industry: Services

gotchas

  • Double-booking risk

    Without real-time calendar locks, simultaneous bookings can collide.

  • Timezone alignment

    Always display host and attendee timezone assumptions in copy.

conversion uplift data

No conversion benchmark was attached to this template yet.

citations

related templates