MailSlurp logo

guides

Email Schema: Gmail Markup, JSON-LD, and How To Test It

Learn what email schema means, how schema.org markup works in Gmail, and how to test structured actions, auth, and delivery before launch.

Use with your tools

Email schema is schema.org data embedded in an HTML email. Gmail can use it to show a useful action, a reservation, an order, or another highlight before the reader goes hunting through the message.

There is one important catch: valid JSON-LD does not guarantee a shiny new button in Gmail. A production sender also needs to meet Google's registration, authentication, reputation, and action-quality requirements. Treat the markup, the delivered message, and the action behind it as three parts of the same feature.

Quick answer: how does email schema work?

Gmail reads supported schema.org markup from either:

  • JSON-LD in the email's <head>; or
  • microdata in the email's HTML body.

The markup describes the message and, when appropriate, the action a person can take. Gmail currently documents in-app actions, go-to actions, and highlights for transactional messages such as orders, parcel deliveries, invoices, ticketed events, and travel or restaurant reservations.

For a production launch, use this order:

  1. Choose a supported schema that matches the message people actually receive.
  2. Add a normal, visible fallback link or button to the email.
  3. Validate the markup with Google's Email Markup Tester.
  4. Send the real template through the real delivery path and inspect the received HTML and headers.
  5. Self-test the Gmail surface, then register the production sender with Google.
  6. Exercise the action endpoint, including expiry, replay, error, and sign-in behavior.

MailSlurp gives that process a controlled inbox, the exact received message, raw headers, and a repeatable API test. Gmail's own self-test and registration flow then confirms what Gmail chooses to surface.

The production rule most email-schema guides miss

Google requires production senders to register before Gmail processes their schemas. Registration is not a final coat of paint. It is part of the implementation plan.

Google's published registration guidelines include:

  • DKIM or SPF authentication;
  • alignment between the authenticated domain and the visible From: domain;
  • a consistent static sender address;
  • a history of sending roughly hundreds of messages a day to Gmail for at least a few weeks;
  • a very low spam-complaint rate; and
  • compliance with Gmail's sender and spam-prevention guidance.

If the sender relies on SPF rather than DKIM, Google checks the Return-Path: domain for SPF and expects it to align with the visible From: domain. That makes DKIM, SPF, From:, and Return-Path: inspection a release requirement, not a box to tick after the template is finished.

Google also asks applicants to send a real, schema-bearing sample directly from production or a production-like system. A blank sample, a forwarded message, or a message without the markup can be discarded. Gmail removes markup when a message is manually forwarded, so the review sample needs to take the front door.

Self-test before you register

Gmail's self-test path lets you send a message from a Gmail account to the same Gmail account. That sender-equals-recipient case ignores the production registration requirement, although DKIM or SPF authentication is still required.

Use self-testing to answer two early questions:

  • Can Gmail parse the markup?
  • Does the resulting action or highlight make sense beside the real email?

It does not replace the production-like send Google requests during registration. A self-test is the dress rehearsal; the production sender, authentication, reputation, and endpoint still have to turn up on opening night.

Pick the action that matches the job

Gmail separates actions into two broad families. Choosing the wrong one can be as unhelpful as putting a revolving door on a fire exit: technically a door, but not the door for the moment.

In-app actions

An in-app action completes a predefined task inside Gmail. Google's one-click examples include confirming or saving something. The action endpoint receives an HTTP request when the person confirms the action.

Use an in-app action only when the result is specific and safe to explain before the click. The endpoint should be HTTPS, validate a short-lived or limited-use token, handle retries safely, and reject expired or already-used requests without creating a second side effect.

Go-to actions

A go-to action sends the person to a specific page on your site. Gmail documents ViewAction and TrackAction for this purpose. Use one when the task needs more steps, meaningful data entry, or a page the reader needs to inspect.

Google's guidelines say the destination should deep-link to the exact task, the label should be short and truthful, and an available in-app action should take precedence. Production approval is intentionally focused on high-value transactional uses such as shipment tracking and flight check-in, not decorative buttons on promotional mail.

Highlights

Highlights expose useful structured details from supported transactional messages. Google documents highlights for areas including:

  • orders and parcel delivery;
  • invoices;
  • bus, car-rental, train, and flight reservations;
  • hotels and restaurants; and
  • ticketed events.

Start from the specific Google reference for your type. Required properties differ. An Order, for example, needs more than an order number, while a reservation needs the people, status, and subject of the reservation expressed in the expected shape.

A complete JSON-LD email example

This minimal ViewAction demonstrates placement and fallback behavior. It does not promise production approval for a particular use case; that decision depends on the sender and workflow requirements above.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Your order is ready to review</title>
    <script type="application/ld+json">
      {
        "@context": "http://schema.org",
        "@type": "EmailMessage",
        "description": "Review order MS-123",
        "potentialAction": {
          "@type": "ViewAction",
          "url": "https://example.com/orders/MS-123",
          "name": "View order"
        }
      }
    </script>
  </head>
  <body>
    <h1>Your order is ready</h1>
    <p>Order MS-123 is ready to review.</p>
    <p><a href="https://example.com/orders/MS-123">View order</a></p>
  </body>
</html>

The visible link is not duplicate clutter. It is the email's dependable path when a client does not support the schema, the sender is not yet registered, or Gmail decides not to display the action.

Keep dynamic values server-generated and escaped. The action URL should identify the correct order without exposing a reusable credential. If it carries a token, make the token narrow, expiring, and safe against replay.

The same idea with microdata

Gmail also accepts microdata in the HTML body:

<div itemscope itemtype="http://schema.org/EmailMessage">
  <meta itemprop="description" content="Review order MS-123" />
  <div itemprop="potentialAction"
       itemscope
       itemtype="http://schema.org/ViewAction">
    <link itemprop="target" href="https://example.com/orders/MS-123" />
    <meta itemprop="name" content="View order" />
  </div>
</div>

JSON-LD is usually easier to spot, generate, and parse in a test because the structured block is separate from the visible message. Microdata can be a sensible fit when a template system already models schema properties alongside HTML. Pick one format for a template family and keep the choice boringly consistent.

Test the exact message, not the hopeful template

There are four separate checks. Passing one does not silently pass the others.

1. Validate the schema shape

Paste the final markup into Google's Email Markup Tester. Fix every parse error and compare the extracted properties with the intended recipient, order, reservation, or action.

The validator checks structured data. It cannot know whether the production template engine will later remove the script, replace a URL with the wrong environment, or produce an email that never arrives.

2. Capture the delivered email

Create a fresh MailSlurp Email Sandbox or test inbox, send the message through the application's normal provider, and inspect what actually arrived.

Check:

  • From:, Return-Path:, DKIM, and SPF results;
  • the complete JSON-LD or microdata block;
  • the visible fallback copy and link;
  • production hostnames and personalized identifiers;
  • plain-text content for clients that do not render HTML; and
  • the absence of secret values in the body, headers, and URLs.

This is where a surprising number of polite-looking templates reveal that they packed a staging link for the journey.

3. Assert the schema in code

The test should wait for the real message, locate the JSON-LD block, parse it as JSON, and compare the action with the customer journey that triggered the email.

import { MailSlurp } from "mailslurp-client";

const apiKey = process.env.MAILSLURP_API_KEY;
if (!apiKey) throw new Error("Set MAILSLURP_API_KEY before this test");

const mailslurp = new MailSlurp({ apiKey });
const inbox = await mailslurp.createInbox();

// Give inbox.emailAddress to the real order or reservation flow here.
const email = await mailslurp.waitForLatestEmail(inbox.id, 60_000, true);
const html = email.body ?? "";

const match = html.match(
  /<script[^>]*type=["']application\/ld\+json["'][^>]*>([\s\S]*?)<\/script>/i,
);
if (!match) throw new Error("The received email had no JSON-LD block");

const schema = JSON.parse(match[1]);
if (schema["@type"] !== "EmailMessage") {
  throw new Error(`Unexpected schema type: ${schema["@type"]}`);
}
if (schema.potentialAction?.url !== "https://example.com/orders/MS-123") {
  throw new Error("The email pointed to the wrong order");
}
if (!html.includes("https://example.com/orders/MS-123")) {
  throw new Error("The visible fallback order link was missing");
}

Use a DOM parser when a template can contain several JSON-LD blocks or unusual HTML escaping. The small expression above is deliberately scoped to one controlled test fixture, not offered as a general-purpose HTML parser.

4. Complete the customer action

Open the visible link and, where applicable, exercise the schema action from the Gmail self-test. Assert the final order, reservation, subscription, or account state.

Also test:

  • a second click on a one-time action;
  • an expired token;
  • a signed-out recipient;
  • an identifier belonging to another account;
  • a provider retry; and
  • an endpoint failure that returns a useful response without partially changing state.

A button appearing in Gmail is a presentation result. The feature is complete when the right person can finish the right task once, safely.

Secure Gmail actions without making the email a keyring

Google's action-security guidance requires registered, authenticated senders and HTTPS action handlers. It also recommends limited-use access tokens to reduce replay risk. Google can provide a bearer token for inline action requests when that option is arranged during registration.

On your side of the endpoint:

  • bind the token to one recipient, purpose, and resource;
  • give it a short and documented lifetime;
  • store or derive enough state to reject replay;
  • make repeated provider requests idempotent;
  • authorize the resource instead of trusting an order ID in the URL; and
  • log a correlation ID and result without logging the full token.

Keep sensitive account changes behind an appropriate confirmation or sign-in boundary. Email schema makes an action easier to reach; it should not make authorization easier to skip.

Diagnose a missing Gmail action

When the visible email arrives but the action does not appear, check the boundaries in this order.

The markup tester reports an error

Fix the schema type and required properties first. Validate the final rendered markup, not a documentation example with placeholder fields.

Self-test works but production does not

Confirm that the production sender is registered, static, and the one Google approved. Inspect DKIM or SPF alignment, From:, Return-Path:, sending history, and complaint rate. Make sure the message was sent directly rather than forwarded.

The action appears but opens the wrong place

Inspect the received URL for environment drift and confirm it deep-links to the exact customer task. Keep the visible fallback link and the schema action generated from the same canonical value.

The endpoint runs twice

Treat action requests as retryable. Use an idempotency key or a consumed-token record so a harmless repeat returns the existing result instead of placing a second order or applying a second change.

Gmail shows no enhancement for some recipients

Do not hide instructions inside the schema. Keep the subject, visible HTML, plain text, and ordinary CTA complete on their own. Client support, recipient context, and Gmail's display decision can vary even when the email remains perfectly useful.

A practical release checklist

Before launch:

  • choose the exact supported action or highlight type;
  • include every required property from its current Google reference;
  • keep a visible HTML link and useful plain-text fallback;
  • validate the final schema with Google's tester;
  • send through the real provider to a fresh MailSlurp inbox;
  • inspect authentication results and sender alignment;
  • assert received structured values and production URLs;
  • test success, expiry, replay, authorization, and endpoint failure;
  • self-test the Gmail presentation;
  • send Google's direct production-like sample and complete registration; and
  • canary the registered sender before broadening traffic.

After a template, domain, provider, or action-endpoint change, run the checks again. Structured email is code wearing a nice shirt. Give it the same release discipline as the page it opens.

FAQ

Does valid JSON-LD guarantee a Gmail button?

No. The markup must be valid, but production display also depends on sender registration, authentication, sender quality, the supported use case, the action endpoint, and Gmail's display decision.

Can I test Gmail email schema without registering first?

Yes. Google documents a sender-equals-recipient Gmail self-test that ignores registration requirements. DKIM or SPF is still required. Register the production sender before sending schema-bearing mail to customers.

Should I use JSON-LD or microdata?

Both are supported. JSON-LD is often simpler to generate and test because it stays in one block. Microdata can suit a template system that already annotates HTML. Consistency and correct received output matter more than fashion.

Is email schema a deliverability feature?

It is a message-experience feature, not a shortcut around delivery. Authentication, sender reputation, inbox placement, rendering, and the fallback message still need their own checks. Use inbox placement testing when placement is part of the release risk.

Can I add a go-to action to a newsletter?

Google's registration guidelines reserve actions for transactional mail with strong expected interaction and say they should not be used on promotional bulk mail. Use a normal, accessible CTA for a newsletter.

What should a MailSlurp test prove?

Prove that the real message arrived with the intended sender and authentication results, retained valid structured data, contained the correct visible fallback, opened the right production action, and let the customer finish the workflow.

Build the feature all the way to the click

Good email schema feels almost invisible: Gmail understands the message, the reader sees one honest next step, and the ordinary email still works everywhere else. Validate the schema, capture the delivered artifact with MailSlurp, self-test Gmail, register the sender, and then test the action as carefully as the message. That is how a clever annotation becomes a dependable customer journey.