SEO Auditor — validates the X (Twitter) Card meta tags so links shared on X render a proper preview.
Social sharing
X builds the card shown under a shared link from the
twitter:* meta tags of the page.Click-through
A card type, title and reachable image make shared links stand out in the timeline and get clicked.
<meta name="twitter:…"> tags X reads when a link is posted. This auditor fetches the page, collects every twitter: meta tag, verifies the two tags every card needs (twitter:card and twitter:title), checks the card type and the tags each card type depends on, checks that twitter:url and twitter:image are absolute and consistent with the page, and probes the twitter:image URL once to confirm it serves a supported image type.
How it works
- Fetch — requests the HTML through the core HTTP fetcher (including HTTP Basic Auth when provided). A blocked request (HTTP 403, 429 or a Cloudflare challenge) ends with
37A-TwitterCardAuditor-590; any other fetch failure produces anERRORresponse with37A-TwitterCardAuditor-500. - Collect — reads every
<meta>whosename(orproperty) starts withtwitter:, keeping document order and repeated values. - Probe — when
twitter:imageis an absolute URL, sends oneHEADrequest (falling back toGETon405) and records the HTTP status andContent-Type; both image rules read that single answer. - Rules — a missing or blank
twitter:cardortwitter:titleis a FAIL. Empty optional tags, duplicated tags, unknowntwitter:tags, an unsupported card type, relative or off-host URLs, card types without the tags they need, an image without alt text, and an unreachable or non-imagetwitter:imageare WARNINGs. - Aggregate —
ERRORwins, thenFAIL, thenWARNING; if every rule passes, the audit isSUCCESS. - Specification pin — every run emits
37A-TwitterCardAuditor-100(INFORMATION) naming the X Cards markup reference. That check does not change overall status.
What it audits
Every row maps to onecheckRule* method and one CheckCode. 37A-TwitterCardAuditor-100 is emitted on every run, including fetch errors. Image rules 312 and 313 only run when twitter:image is absolute, and 313 is skipped when 312 fires. Card type comparisons ignore case. CheckCode suffixes use status ranges: 100 information, 200 success, 300–399 warning, 400–499 fail, 500–599 error.
Output documentation
Risks and considerations
Required tags
twitter:cardselects the layout andtwitter:titleis the headline; without either, X shows a bare link. X falls back toog:title,og:descriptionandog:imagefor the other fields, but not for the card type.- A required tag with an empty
contentis as bad as a missing one and is harder to spot in a template, so it fails rather than warns.
Card types
- Only
summary,summary_large_image,appandplayerrender;photo,galleryandproductcards were retired and now produce no preview. - A
summary_large_imagecard needstwitter:image; aplayercard needstwitter:playerwithtwitter:player:widthandtwitter:player:height; anappcard needs at least onetwitter:app:name:*platform. - Comparisons of the card type ignore case, so
Summarypasses303but is still worth normalising.
URLs and the preview image
twitter:urlis not part of the current markup reference but is widely used; when present it should be the canonical absolute URL on the page host, otherwise the card is attributed to another address.twitter:imagemust be an absolute, publicly fetchable URL served as JPEG, PNG, GIF or WebP (SVG is not rendered). A403,404or timeout leaves the card without a picture.- The auditor probes with
HEADfirst and retries withGETon405; servers that rejectHEADwith other status codes will warn under312. twitter:image:alt(up to 420 characters) is read by screen readers; it is a warning, not a failure, because the card still renders without it.
Repeated, empty and unknown tags
- X uses the first occurrence of a repeated tag; repeating
twitter:titleortwitter:imageis ambiguous and usually a template leftover. - An optional tag with an empty
contentis treated as the final value, so it should be filled or removed. - Known tags are the ones listed in the markup reference plus
twitter:url,twitter:domain,twitter:player:stream:content_typeandtwitter:app:country; any othertwitter:tag warns so a typo in a tag that matters (for exampletwitter:imag) is caught.