What Is Speakable and How Do You Implement It in 2026?
Speakable is a schema.org property that names the two or three sentences on a page a machine should read aloud or quote. This page covers the JSON-LD, the xpath alternative, a build check that keeps the selectors honest, and what Google actually supports today.
Speakable (schema.org/speakable) is a schema.org property that points at the specific sections of an article or web page best suited to being read aloud, addressed by a CSS selector, an XPath expression, or a plain fragment URL. It exists so a text-to-speech system can lift one coherent short passage instead of narrating the whole page. Google supports it in beta for English-language news content only, so treat it as a cheap, honest hint about your page rather than a distribution channel.
Why Speakable matters for AI visibility
Be clear-eyed about vendor support first. Google's Speakable documentation still carries a BETA label, was last updated on 10 December 2025, and restricts the feature to users in the United States with Google Home devices set to English and to publishers who publish in English. The consumer it describes, Google Assistant answering topical news queries on smart speakers, is being retired: Gemini for Home replaced Assistant across Google's speakers and displays from late 2025, and Assistant is being phased out on Android through 2026. Google's own guidance on AI features says plainly that no new markup is required to appear in AI Overviews or AI Mode. Nobody should ship Speakable expecting traffic from it.
The property is still worth adding, for a different reason. Answer engines do not summarise pages so much as lift passages from them, and the exercise Speakable forces on you is exactly the one that makes a page liftable: choose the single passage that answers the page's question, write it so it survives being quoted with no surrounding context, and give it a stable, addressable home in the DOM. The markup is a few lines of JSON-LD, it is machine-readable to anything that parses schema.org rather than only to Google, and Glippy scores it under Structured Data. The structural half of the job, a tight lead paragraph and question-shaped headings, does the work whether or not the markup is ever consumed. If citability is the part you care about, the conceptual explanation lives here.
Where the spec lives
Two schema.org pages define the property, one vendor page defines what is actually consumed, and one tool actually validates it. Read them in that order.
- schema.org/speakable - the property definition, its two accepted value types (SpeakableSpecification and URL), and the three content-locator forms. Reach for it to confirm which types the property is valid on: Article and WebPage.
- schema.org/SpeakableSpecification - the type behind the markup. It has exactly two properties of its own, cssSelector and xpath, and this page is where you confirm their canonical lowercase spelling.
- Google Search Central: Speakable (BETA) - the only vendor implementation guidance in existence, including the 20 to 30 seconds per section rule, the ban on marking datelines and captions, and the US English eligibility limit.
- Google Search Central: AI features and your website - Google's position that no extra files or markup are needed for AI Overviews or AI Mode. Read it before you promise anyone that Speakable will win citations.
- Schema Markup Validator - the tool that will actually parse and report your speakable node. The Rich Results Test ignores it, because Speakable produces no rich result.
- schemaorg/schemaorg issue 1389 - the design discussion cited as the source on the property page, useful for understanding why three different locator forms exist.
Three ways to implement Speakable
The three approaches differ in how they address the passage and in how you stop it rotting. Use the cssSelector version when you control the article template, use xpath when the sentence you want lives in the document head and has no class to target, and add the build check once more than one person is allowed to edit the template.
Mark one summary with cssSelector
The default. Point the selector at a headline element and one summary paragraph, which is the pattern Google documents. Write the summary as a standalone answer sentence so it reads correctly when it is quoted with nothing around it.
<article class="post">
<h1 class="headline">What does an EU AI Act conformity assessment involve?</h1>
<p class="summary">A conformity assessment is the pre-market check that a
high-risk AI system meets the EU AI Act requirements. Providers run it
themselves for most Annex III systems, and a notified body runs it for
remote biometric identification.</p>
<p>The rest of the article follows here, with the detail and the sources.</p>
</article>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "NewsArticle",
"headline": "What does an EU AI Act conformity assessment involve?",
"datePublished": "2026-08-27T09:00:00+02:00",
"dateModified": "2026-08-27T09:00:00+02:00",
"author": { "@type": "Organization", "name": "Example Newsroom" },
"publisher": { "@type": "Organization", "name": "Example Newsroom" },
"mainEntityOfPage": "https://example.com/ai-act-conformity-assessment",
"speakable": {
"@type": "SpeakableSpecification",
"cssSelector": [".headline", ".summary"]
}
}
</script>
What this does: it tells any consumer that the answerable part of this page is two elements totalling about 45 words, roughly 20 seconds of speech, rather than the full article. The selectors are real CSS with leading dots, and they must match elements that exist in the served HTML, not in a client-rendered view.
Target head elements with xpath
Use this when the passage you want to expose is the title tag and the meta description, or when a legacy template gives you no class names to hook. It also suits a WebPage node on a non-article page, such as a documentation or product page, where there is no Article to hang the property on.
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "EU AI Act conformity assessment",
"url": "https://example.com/ai-act-conformity-assessment",
"speakable": {
"@type": "SpeakableSpecification",
"xpath": [
"/html/head/title",
"/html/head/meta[@name='description']/@content",
"/html/body//main//p[@id='answer']"
]
}
}
What this does: it addresses the passage by document position instead of by class, which survives a CSS refactor but breaks the moment anyone reorders the markup. Mind the spelling: schema.org defines the property as xpath, all lowercase, and that is the only term its JSON-LD context resolves, while Google's documented sample writes xPath. Google says to use either cssSelector or xpath in one SpeakableSpecification, never both.
Verify every selector at build time
Speakable fails silently. A class rename, a CSS-modules hash or a component swap leaves valid JSON-LD pointing at nothing, and no tool will tell you. Run this against the built HTML in CI so the selectors and the DOM cannot drift apart.
// node scripts/verify-speakable.mjs dist/ai-act-conformity-assessment/index.html
// requires: npm i -D cheerio
import { readFileSync } from 'node:fs';
import { load } from 'cheerio';
const WORDS_PER_SECOND = 2.5; // about 150 words per minute of TTS
const $ = load(readFileSync(process.argv[2], 'utf8'));
const nodes = [];
$('script[type="application/ld+json"]').each((_, el) => {
const data = JSON.parse($(el).text());
nodes.push(...(Array.isArray(data) ? data : data['@graph'] || [data]));
});
const spec = nodes.find((n) => n && n.speakable)?.speakable;
if (!spec) throw new Error('speakable: no speakable property in any JSON-LD block');
const selectors = [].concat(spec.cssSelector || []);
if (!selectors.length) throw new Error('speakable: no cssSelector to verify');
let words = 0;
let failed = false;
for (const sel of selectors) {
const found = $(sel);
if (found.length !== 1) {
console.error(`speakable: "${sel}" matched ${found.length} elements, expected 1`);
failed = true;
continue;
}
const text = found.text().replace(/\s+/g, ' ').trim();
words += text ? text.split(' ').length : 0;
}
const seconds = Math.round(words / WORDS_PER_SECOND);
console.log(`speakable: ${selectors.length} selectors, ${words} words, about ${seconds}s`);
if (seconds > 30) {
console.error('speakable: over the 30 second guideline, trim the summary');
failed = true;
}
process.exit(failed ? 1 : 0);
What this does: it resolves each cssSelector against the rendered HTML, fails when a selector matches zero or several elements, and converts the marked word count into an audio estimate so the passage stays inside Google's 20 to 30 second guideline. The same check doubles as a citability gate: if the selected text is empty, no answer engine can lift it either.
Implementation guidelines
The failures here are boring and repeatable: selectors that stop matching, passages that read as fragments, and markup pointed at boilerplate.
- Pick the passage before you pick the selector. Write one self-contained sentence that answers the page's main question without needing the heading above it, then give that element a class. Doing it in the other order produces markup around whatever paragraph happened to be first.
- Stay inside the 20 to 30 second budget. Google recommends roughly two to three sentences per speakable section, which is about 50 to 75 words at normal TTS speed. A whole article marked speakable gets cut off mid-thought.
- Use a class your build will not rename. CSS modules, Tailwind and styled-components all generate or churn class names. Add a semantic hook such as
speakable-summaryor anidthat exists purely for addressing, and never style it. - Keep the selector target in the server-rendered HTML. If the summary is injected by client-side JavaScript, a crawler that does not execute scripts resolves the selector to nothing. Server-render the marked passage even if the rest of the page hydrates.
- Pick one locator form and spell it correctly. cssSelector and xpath are mutually exclusive inside a single SpeakableSpecification. cssSelector has one spelling and is the safer default; use lowercase
xpathper schema.org unless you are specifically targeting Google's beta, whose sample usesxPath. - Attach speakable to the node that owns the content. The property is defined for Article and WebPage only. Putting it on an Organization node, or nesting it under
mainEntity, produces markup that validates loosely but is not found by parsers that look for it on the article node. - Validate with the Schema Markup Validator. The Rich Results Test will not report Speakable, because it generates no rich result, and its silence is not an error. Use validator.schema.org for syntax and your own build check for whether the selectors resolve.
Do this, not that
Do
- Point cssSelector at a headline element plus exactly one summary element, the pattern in Google's own sample.
- Write the summary as a sentence that still parses when quoted alone, with the subject named rather than referred to as "it" or "this".
- Keep the marked text under about 75 words, which is roughly 30 seconds of synthesised speech.
- Re-run the selector check whenever the article template, the CSS strategy or the component library changes.
Do not
- Do not point a selector at the whole
<article>element and call it a summary. - Do not put cssSelector and xpath in the same SpeakableSpecification object.
- Do not mark datelines, photo captions, bylines or source attributions, which Google explicitly tells you to skip.
- Do not sell Speakable as an AI Overviews or AI Mode tactic, since Google states no extra markup is required for those surfaces.
How Glippy checks this
Glippy scores Speakable inside Structured Data, category 1, where the check is worth 10 of that category's 100 points. It parses every application/ld+json block on the page, flattens top-level arrays and @graph members into individual nodes, and passes when any of those nodes carries a speakable key. It also accepts the microdata form, an element with itemprop="speakable". A page with no Speakable markup is reported as informational at 0 of 10 rather than as a failure, because the property is optional. One consequence of the flattening rule is worth knowing: a speakable buried inside a nested property such as mainEntity is not seen, so keep it on the Article or WebPage node itself.
Check your Speakable setup
Glippy runs 240+ checks across 16 categories on any page, including Structured Data (category 1). No sign-up required.
Frequently asked questions
Yes, but narrowly, and the documentation has not kept up. Google's Speakable page still carries a BETA label, was last updated on 10 December 2025, and limits the feature to users in the United States with Google Home devices set to English and to publishers publishing in English. The surface it describes, Google Assistant reading topical news on smart speakers, has been superseded by Gemini for Home since late 2025, and Assistant is being retired on Android through 2026. Add the markup because it is cheap and standards-based, not because it will send you traffic.
No. In schema.org version 30.0, dated 19 March 2026, both speakable and SpeakableSpecification sit in the core vocabulary rather than the pending extension, and the property page reports adoption on 100,000 to 1,000,000 domains. speakable is defined on Article and WebPage, and accepts either a SpeakableSpecification object or a URL. SpeakableSpecification has exactly two properties of its own, cssSelector and xpath.
Use cssSelector in almost every case. It is shorter, it tolerates markup being reordered, and it has a single unambiguous spelling. Reach for xpath when the text you want lives in the document head, such as the title element or the meta description content attribute, where there is no class to target. Google's guidance is to use one or the other in a single SpeakableSpecification and never both, and note that schema.org spells the property xpath while Google's sample writes xPath.
There is no published evidence that it does, and Google states directly that no new files or markup are needed to appear in AI Overviews or AI Mode. What does help is the page structure the property forces you to build: a single self-contained sentence that answers the page's question, placed high in the server-rendered HTML, followed by question-shaped headings that a model can match to a query. Ship the markup as a cheap machine-readable signal, but rely on the passage itself.
Reviewed against the primary sources on . These standards move quickly, so check the linked specs before you ship.