SEO
Article schema step by step, without duplicates
Article is the schema.org type that describes a post: headline, dates, author, image. Add it once per page, with the data already visible on the page.
Key points
- Article describes a published article and belongs once per page, with the values the reader sees.
- On the production site the article page serves 2 JSON-LD blocks holding 7 nodes, Article included, read on 1 November 2026.
- A duplicate Article node, or a date bumped on every deploy, cancels the information the markup was supposed to carry.
Article is the schema.org type that describes a published article: headline, dates, author, image. You add it as JSON-LD on the page, once, with the same values the reader sees.
What Google asks for
The Article page, read on 1 November 2026, says the markup helps Google show better title text, images and date information in the result, and that no markup requirement exists for entering Google News features. The official example uses NewsArticle with headline, image, datePublished, dateModified and author. BlogPosting and NewsArticle are subtypes of Article: pick the one that describes the page, not the biggest one.
The complete block
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Come aggiungere schema markup senza rompere il sito",
"datePublished": "2026-11-01T21:45:00+01:00",
"dateModified": "2026-11-01T21:45:00+01:00",
"author": {
"@type": "Person",
"name": "Enea Zani",
"url": "https://eneawork.it"
},
"image": ["https://ui.eneawork.it/blog-covers/it/come-aggiungere-schema-markup.png"],
"mainEntityOfPage": {
"@id": "https://ui.eneawork.it/it/blog/come-aggiungere-schema-markup"
}
}
The block carries the five fields from the example, plus mainEntityOfPage, which states the URL the article belongs to. image is an array: one image is fine, but the array saves you from rewriting the block when a second one arrives. author is a Person object with a URL that resolves: an author with no page is a name, not an entity.
Checking the node before deployment
cat > check-article.mjs ]*application\/ld\+json[^>]*>([\s\S]*?)/g)];
const nodes = blocks.flatMap(([, raw]) => {
const data = JSON.parse(raw);
return data["@graph"] || [data];
});
const article = nodes.find((n) => /^(Article|NewsArticle|BlogPosting)$/.test(n["@type"]));
if (!article) {
console.log("no Article node");
process.exit(1);
}
const missing = ["headline", "datePublished", "author", "image"].filter((k) => !article[k]);
console.log(`${nodes.length} JSON-LD nodes, Article ${article["@type"]}`);
console.log(missing.length ? `missing: ${missing.join(", ")}` : "required fields present");
EOF
node check-article.mjs https://ui.eneawork.it/blog/come-aggiungere-schema-markup
The script fetches the page, flattens the nodes of every block (including anything inside @graph) and looks for the first Article, NewsArticle or BlogPosting. It then lists the properties missing against the example. A missing node is a deployment error, not a validator error: no tool knows that the type was supposed to be there.
Four errors you will see often
- Two Article nodes on one page, one from the CMS and one from the component: Google picks one and the data contradicts itself.
- dateModified bumped on every deploy instead of on every real edit: the date loses meaning and Google ignores it.
- headline different from the visible H1: the markup describes text the reader cannot see, which is the definition of misleading markup.
- image pointing at a 404: the image is the visible part of the result, and an error there shows immediately.
The live record
One catalogue record already has the right shape: glass-blog-card-shadcnui renders a title, a date and preview text, three of the fields Article reuses. The lists to start from are blog and the 1,556 blocks. Checked on 1 November 2026.
The limitation
Article does not produce a rich result on its own and does not move the position. It exists so Google can read data already on the page and make fewer guesses when two pages look alike. When the markup contradicts visible text, Google applies a manual action: no validator sees that difference, because the comparison is semantic.
Where to continue
The introduction to the format is in how to add schema markup; the markup for questions is in FAQPage schema; the sequence for getting into the index is in getting a site indexed by Google. On WordPress or on React components, whoever generates the JSON-LD changes: the comparison is in WordPress, Wix or React components.
Frequently asked questions
Article, NewsArticle or BlogPosting?
Whichever describes the page: BlogPosting for a blog, NewsArticle for a newsroom, Article when neither is precise. All three share the same properties.
Is the image required?
In Google's example it is, and in practice always worth it: it is the most visible part of the result. It must return 200 and use a format Google indexes.
Where does the Article block go?
In the page HTML, in the head or the body, inside a script tag with type application/ld+json. It must not sit inside another script.
Can I use one block with @graph?
Yes, and that is what this site does: 2 scripts holding 7 nodes, with Article next to Organization and BreadcrumbList. What matters is that each entity appears once, with consistent data.
Must datePublished and dateModified be ISO 8601?
Yes. Google accepts a date and time with a timezone, for example 2026-11-01T21:45:00+01:00. A date without a timezone gets interpreted, and the interpretation is not always the one you meant.