agentsclimarketplace

Seo schema writer

Skill avikbal-dm/seo-schema-writer

Write correct, validated, paste-ready JSON-LD for any page, tuned for both classic Google rich results and the entity signals that AI engines read. Picks the right types, fills them with real values from the page, links entities in one clean @graph, and closes by telling you where to paste it and how to test it. Covers Organization, WebSite, WebPage, Article, BreadcrumbList, Product, Review, Service, Person, Event, JobPosting, Video, and the GEO and AIO layer most tools skip: sameAs, knowsAbout, about, mentions, DefinedTerm, QAPage, speakable, citation. Use when someone wants schema written or generated, JSON-LD, structured data, entity markup, or AI search and GEO markup for a page. It writes the markup. For audits and strategy, use structured-data-engine.From its SKILL.md

Install
npx -y skills add avikbal-dm/seo-schema-writer

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

17.1 KB, ~4.2k tokens by cl100k_base, as published. Nobody here has run it

SEO Schema Writer

What this does

You hand it a page. It hands back the JSON-LD you paste in, built from the real content on that page, validated, and tuned for two audiences at once: Google rich results that still exist in 2026, and the AI engines that read your markup to understand and cite you.

It does not stop at the code. Every run ends with a short, practical handoff: where to paste the block, what it is eligible for, and the two links you use to test it. You should never have to guess whether the markup works.

Two rules sit under everything here. Mark up only what a visitor can see on the page. Never invent a value to win a feature. A fabricated rating or a fake review is a manual action waiting to happen, with your domain attached.

When to use it

Reach for it when you want schema written for a new page, when existing markup will not validate, or when you are building the entity graph for a whole site. For deciding which features are worth chasing and auditing what already exists, run structured-data-engine first, then bring those decisions here to write.

What to give it

Accurate input makes accurate output. Useful to share:

  • The URL, or the visible content of the page.
  • The page type and intent: home, article, product, service, comparison, glossary, author bio, event.
  • Brand identity: legal name, logo URL, and the profiles to link as sameAs (LinkedIn, Crunchbase, Wikidata, Wikipedia if one exists).
  • Author identity for content pages: name, role, employer, and profile or credential links.
  • Real commercial data where it applies: price, currency, availability, and genuine rating or review data. Real numbers only.
  • The topics the page and the brand have genuine authority on, for knowsAbout and entity linking.

When a value is missing, it asks or leaves a clearly marked field. It does not fill the gap with a guess.

The output format

JSON-LD only, never microdata. One <script type="application/ld+json"> block per page, with the entities connected in a single @graph and joined by @id. That keeps the page readable as one coherent entity rather than a pile of disconnected blocks. The shell looks like this, and the type templates below slot into the graph:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@graph": [
    { "...Organization..." },
    { "...WebSite..." },
    { "...WebPage..." },
    { "...the page's main type, e.g. Article or Product..." }
  ]
}
</script>

Foundation: the site-wide entity

Write these once, keep the @id values stable, and reference them from every page. This is what makes a search engine and an AI model read your whole site as one known entity.

Organization, the brand's root identity:

{
  "@type": "Organization",
  "@id": "https://example.com/#organization",
  "name": "Example Inc",
  "url": "https://example.com/",
  "logo": {
    "@type": "ImageObject",
    "url": "https://example.com/logo.png",
    "width": 512,
    "height": 512
  },
  "sameAs": [
    "https://www.linkedin.com/company/example",
    "https://www.crunchbase.com/organization/example",
    "https://www.wikidata.org/wiki/Q00000000"
  ],
  "knowsAbout": ["Core Topic One", "Core Topic Two", "Core Topic Three"]
}

WebSite, which also declares your internal search for the sitelinks search box:

{
  "@type": "WebSite",
  "@id": "https://example.com/#website",
  "url": "https://example.com/",
  "name": "Example",
  "publisher": { "@id": "https://example.com/#organization" },
  "potentialAction": {
    "@type": "SearchAction",
    "target": {
      "@type": "EntryPoint",
      "urlTemplate": "https://example.com/?s={search_term_string}"
    },
    "query-input": "required name=search_term_string"
  }
}

WebPage, the page wrapper. Use the precise subtype where one fits: AboutPage, ContactPage, ProfilePage, CollectionPage, or plain WebPage:

{
  "@type": "WebPage",
  "@id": "https://example.com/page/#webpage",
  "url": "https://example.com/page/",
  "name": "Page Title",
  "isPartOf": { "@id": "https://example.com/#website" },
  "primaryImageOfPage": { "@type": "ImageObject", "url": "https://example.com/page/hero.jpg" },
  "datePublished": "2026-06-01T08:00:00+00:00",
  "dateModified": "2026-06-15T10:00:00+00:00"
}

Author identity: the E-E-A-T and trust signal

A named author rendered as a full Person entity, linked to credentials, is one of the strongest trust signals you can ship. It feeds Google's understanding of who stands behind the content, and it gives AI engines a real person to attribute.

{
  "@type": "Person",
  "@id": "https://example.com/author/jane#person",
  "name": "Jane Doe",
  "jobTitle": "Head of Research",
  "worksFor": { "@id": "https://example.com/#organization" },
  "url": "https://example.com/author/jane/",
  "sameAs": [
    "https://www.linkedin.com/in/janedoe",
    "https://orcid.org/0000-0000-0000-0000",
    "https://scholar.google.com/citations?user=XXXX"
  ],
  "knowsAbout": ["Topic One", "Topic Two"]
}

Content: Article, with the freshness and source signals AI reads

For posts, guides, and news. Use BlogPosting, Article, or NewsArticle to match the page. Note dateModified for freshness, about and mentions for entity linking, and citation and isBasedOn to show your sources, all of which help AI engines trust and quote the page.

{
  "@type": "BlogPosting",
  "@id": "https://example.com/post/#article",
  "isPartOf": { "@id": "https://example.com/post/#webpage" },
  "mainEntityOfPage": { "@id": "https://example.com/post/#webpage" },
  "headline": "The Visible H1, Under 110 Characters",
  "description": "One-line summary that matches the page.",
  "image": "https://example.com/post/hero.jpg",
  "datePublished": "2026-06-01T08:00:00+00:00",
  "dateModified": "2026-06-15T10:00:00+00:00",
  "author": { "@id": "https://example.com/author/jane#person" },
  "publisher": { "@id": "https://example.com/#organization" },
  "about": [
    { "@type": "Thing", "name": "Primary Topic", "sameAs": "https://www.wikidata.org/wiki/Q00000" }
  ],
  "mentions": [
    { "@type": "Thing", "name": "Named Entity", "sameAs": "https://en.wikipedia.org/wiki/Named_Entity" }
  ],
  "citation": ["https://primary-source.com/study", "https://second-source.com/report"],
  "isBasedOn": "https://primary-source.com/study",
  "speakable": {
    "@type": "SpeakableSpecification",
    "cssSelector": ["h1", ".key-takeaways"]
  }
}

BreadcrumbList: still a live rich result

{
  "@type": "BreadcrumbList",
  "itemListElement": [
    { "@type": "ListItem", "position": 1, "name": "Home", "item": "https://example.com/" },
    { "@type": "ListItem", "position": 2, "name": "Category", "item": "https://example.com/category/" },
    { "@type": "ListItem", "position": 3, "name": "This Page" }
  ]
}

The GEO and AIO layer

This is the part most schema tools skip, and it is where the gains now sit. Be honest about what it does. Google states there is no special markup that gets you into AI Overviews or AI Mode, and schema must always match the visible page. What schema does is make your entities, definitions, and sources unambiguous to machines, which is exactly what retrieval and citation depend on across Google, Bing, Perplexity, ChatGPT, and the rest.

Entity identity. The single highest-leverage move: stable @id across the site, plus sameAs pointing at the authoritative records for your brand and authors (Wikidata, Wikipedia, LinkedIn, Crunchbase, ORCID). This disambiguates who you are. Pair it with knowsAbout on the Organization and Person to declare topical authority, and about and mentions on content to link it to known entities.

DefinedTerm and DefinedTermSet. For glossaries and definitional content. AI engines lean on clean, source-able definitions, and this marks yours as exactly that.

{
  "@type": "DefinedTermSet",
  "@id": "https://example.com/glossary/#termset",
  "name": "Industry Glossary",
  "hasDefinedTerm": [
    {
      "@type": "DefinedTerm",
      "@id": "https://example.com/glossary/term-slug/#term",
      "name": "Term Name",
      "description": "The exact visible definition shown on the page.",
      "inDefinedTermSet": { "@id": "https://example.com/glossary/#termset" },
      "sameAs": "https://www.wikidata.org/wiki/Q00000"
    }
  ]
}

QAPage. For a single user-style question with answers, such as a community or support thread. Different from FAQPage, and it can still surface in places FAQ no longer does.

{
  "@type": "QAPage",
  "mainEntity": {
    "@type": "Question",
    "name": "The question in plain words?",
    "text": "The full question as written on the page.",
    "answerCount": 1,
    "acceptedAnswer": {
      "@type": "Answer",
      "text": "The full accepted answer as shown on the page.",
      "upvoteCount": 12,
      "url": "https://example.com/thread/#answer1"
    }
  }
}

FAQPage. As of May 7, 2026, this no longer earns a Google rich result, and it earns none for any site, including the health and government pages that kept it after 2023. The type stays valid, Google still parses it to understand the page, and AI crawlers still read it. So write it when the page has genuine question-and-answer content worth making legible to machines. Do not write it to win SERP real estate, because that is gone.

{
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "A real question on the page?",
      "acceptedAnswer": { "@type": "Answer", "text": "The visible answer, no marketing fluff." }
    }
  ]
}

speakable. Marks the sections fit for voice and text-to-speech. Support is limited and largely tied to news, so treat it as a forward signal rather than a guaranteed feature, and point the cssSelector at your headline and summary.

ImageObject and VideoObject. Multimodal matters more every quarter, and Video still earns a real rich result. Give images and video real metadata, license, and creator.

{
  "@type": "VideoObject",
  "name": "Video Title",
  "description": "What the video shows.",
  "thumbnailUrl": "https://example.com/video/thumb.jpg",
  "uploadDate": "2026-06-01T08:00:00+00:00",
  "duration": "PT5M30S",
  "contentUrl": "https://example.com/video/file.mp4",
  "embedUrl": "https://example.com/video/embed"
}

Commercial and vertical types

Product, with Offer and genuine ratings, still a core rich result:

{
  "@type": "Product",
  "name": "Product Name",
  "image": "https://example.com/product.jpg",
  "description": "What it is.",
  "brand": { "@type": "Brand", "name": "Example Inc" },
  "offers": {
    "@type": "Offer",
    "price": "99.00",
    "priceCurrency": "USD",
    "availability": "https://schema.org/InStock",
    "url": "https://example.com/product/"
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.6",
    "reviewCount": "128"
  }
}

SoftwareApplication, for SaaS:

{
  "@type": "SoftwareApplication",
  "name": "Product Name",
  "applicationCategory": "BusinessApplication",
  "operatingSystem": "Web",
  "offers": { "@type": "Offer", "price": "0", "priceCurrency": "USD" }
}

Also available on request, each written the same way: Service, LocalBusiness with address and geo, Event, JobPosting, Recipe, Course, and Dataset. Each is filled only from visible page values.

What still earns a rich result in 2026

Worth knowing so effort lands where a feature still exists.

Still earns one when the page qualifies: Article, BreadcrumbList, Product and merchant listings, Review and AggregateRating, Recipe, Event, Video, JobPosting, LocalBusiness, and Organization for the logo and knowledge panel.

No longer earns one, though the markup stays valid and useful for machines and AI: FAQPage, retired May 7, 2026, HowTo, retired earlier, and the seven types Google pruned in June 2025 (Book actions, Course info, Claim review, Estimated salary, Learning video, Special announcement, Vehicle listing).

How it writes

  1. Read the page and name its type, then choose the one or two schema types that fit, led by the rich result still worth winning.
  2. Pull every value from the visible content. Names, prices, dates, authors, ratings, and definitions come from the page, never from a guess.
  3. Build the foundation entities once, with stable @id and sameAs, and reference them from the page type.
  4. Add the GEO and AIO layer where it is genuine: entity links, knowsAbout, about, mentions, definitions, citations, freshness.
  5. Assemble one @graph, validate it against the schema.org spec, and confirm every property maps to something a visitor can see.
  6. Return the block, then the closing handoff below.

The closing handoff, every time

After writing the markup, always end the response with this, filled in for the page:

  • Where to paste: place the block just before </head>, or inject it through your CMS or tag manager. One block per page.
  • What it is eligible for: name the live rich result if any, and note the parts that are for machine and AI understanding rather than a SERP feature.
  • Test it before you ship:
  • One reminder: if you change a visible value later, change the markup in the same edit.

Never hand back markup without this. The user should leave knowing where it goes and how to prove it works.

Example prompts

Copy and adapt:

  • "Write the foundation @graph for my site: Organization, WebSite, and a WebPage. Logo [url], profiles to link [LinkedIn, Wikidata]."
  • "Generate BlogPosting schema for this post: [url or paste]. Author [name, role], published [date], updated [date]. Link the topics to Wikidata."
  • "Write Product schema for this page with the real price and our genuine aggregate rating: [details]."
  • "Build DefinedTermSet schema from this glossary page: [paste terms and definitions]."
  • "Add Person schema for this author bio, linked to LinkedIn and ORCID: [details]."
  • "Write FAQPage markup for these genuine Q and As, and tell me plainly what it still earns in Google: [list]."
  • "Add speakable and citation markup to this article so AI engines read it cleanly: [paste]."
  • "Fix and re-validate the schema on [url] so it matches the visible content, then give me the test links."

Guardrails

  • Mark up only what is visible. Invisible or mismatched schema risks a manual action.
  • Never fabricate ratings, reviews, prices, dates, or entities. Real values only, or a marked field for the user to fill.
  • Match markup to a feature that still exists. Do not present FAQ or HowTo as a 2026 SERP feature.
  • JSON-LD over microdata. One @graph per page over scattered blocks. Stable @id across the site.
  • Keep no promotional language inside answer, description, or definition fields. It breaks eligibility and reads as spam.
  • Validate before shipping, and keep markup and visible content in the same commit. Drift between them is the most common long-term schema failure.

How to use this, a note from the creator

Schema does not lift rankings on its own. It makes a page legible to machines, eligible for the features that still exist, and easy for AI engines to read and quote. So treat it as plumbing that earns its keep, not a growth hack, and the work pays off for years.

Three habits separate schema that works from schema that rots. Give the writer the real page, so every value is true. Build your entity once, with a stable @id and honest sameAs, so search engines and AI models read your whole site as one known thing instead of a stranger on every URL. And test before you paste, every time, using the Rich Results Test and the schema validator. Markup you have not validated is a guess wearing a suit.

The rest is judgment. Add a feature type when the feature still exists. Add the entity and definition layer because it helps a machine understand you, not because you expect a badge. Match the markup to what a reader can see. Do that, and your structured data quietly does its job long after the trend pieces have moved on.

Avik Bal

About the author

Avik Bal is a B2B digital marketing practitioner specializing in web architecture, SEO, content strategy, and marketing analytics. He has helped enterprise software, fintech, and technology companies drive growth through scalable digital marketing programs. Avik is the author of CITED: The Growth Operating System for AI Search.

Part of the Growth Operating System. https://github.com/avikbal-dm/claude-seo-skills

Keep looking

Skills are one crate of 326,499. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.