SEO
The per-entity SEO meta group, the Schema.org type wizard, structured content, the live score engine, and workspace-level publisher defaults.
Clog ships a Yoast / RankMath-grade SEO surface that runs across every content entity (Post, Page, Category, Tag, Author) plus a workspace-level defaults page. This is the longest page in the dashboard guide because the SEO surface is the most-featured part of Clog.
You'll meet five distinct pieces here:
- The per-entity SEO meta group — title, description, canonical, focus keyword, robots, OG, Twitter — sitting in a tab on every content edit page.
- The create-time type wizard (Posts only) — picks the Schema.org variant when you create a new post.
- The Post details structured-content section — type-specific fields (recipe ingredients, how-to steps, event dates, ...) that ship as both reader-facing content and crawler JSON-LD.
- The live score engine — 25 checks (12 SEO + 12 readability + 1 overlap) that grade your post as you type.
- The Workspace SEO defaults page — site name, title template, publisher Organization, social handles, search-console verification codes.
Permission gating
The SEO surface gives an SEO specialist most of what they need without touching content. Two scopes apply:
| What | Required |
|---|---|
Per-entity meta fields (title, description, canonicalUrl, focus keyword, secondary keywords, robots, OG, Twitter, breadcrumbs title) | <entity>:write OR seo:write |
Post schemaType and structuredData (the reader-facing structured content) | posts:write only — it's content, not metadata, so seo:write doesn't unlock it |
| Workspace SEO defaults (read) | settings:read OR seo:read |
| Workspace SEO defaults (write) | settings:write AND seo:write |
In practice: hand seo:write to your SEO specialist and they can tune titles, descriptions, robots, and social metadata across every entity. To let them touch a recipe's ingredients or a how-to's steps, you'd also need to give them posts:write — at which point they're a content editor too.
The per-entity SEO meta group
Every content entity (Post, Page, Category, Tag, Author) carries the same SEO meta object. On the Post and Page edit pages it lives in a right-hand drawer opened by the SEO icon in the top bar; on Category, Tag, and Author edit dialogs it's a dedicated tab in the same dialog.
Three sub-tabs:
General
| Field | What it does |
|---|---|
| Meta title | Overrides the entity's title when emitted in <title> and og:title. Optional. Leave blank to use the entity title via the workspace title template (e.g. My Post — My Blog). |
| Meta description | The string consumer sites stamp into <meta name="description"> and og:description (when no OG override). 120–160 chars is the sweet spot — the live score grades this. |
| Canonical URL | Tell crawlers a different URL is the canonical version of this entity. Use when you syndicate content. |
| Focus keyword | The main search term this entity targets. Drives most of the SEO score's checks. Set to leave the rest blank if you don't care about scoring. |
| Secondary keywords | Up to 5 additional terms. Affect a subset of the score's checks. |
| Robots | Boolean toggles for index, follow, archive, imageIndex, snippet, plus optional caps on snippet length and image / video preview sizes. Defaults inherit from the workspace's default robots block. |
| Breadcrumbs title | Override the entity's title in the breadcrumb trail. Useful for shorter labels on long titles. |
| No-index reason | A free-text note explaining why robots.index = false, for editorial bookkeeping. Not emitted on the API. |
| Redirect to | When set, this entity 301s to the given path. Useful for retired URLs that you want to keep authoring around. |
Social
| Field | What it does |
|---|---|
| OG title / description / image / type | Overrides for Open Graph. The image is picked from the media library; the URL is resolved automatically on the API. |
| Twitter card | One of summary, summary_large_image, player, or app. |
| Twitter title / description / image / creator | Per-entity overrides. creator is a @handle. |
If a Twitter or OG field is empty, the consumer falls back to the General tab's title / description and the workspace's defaultOgImageMediaId.
Analysis
Only present on Posts. Shows the live score — see The live score engine below.
Schema.org variants (Posts)
A Post carries a schemaType (defaults to BlogPosting) selected at create time via a 3-step wizard. v1 covers a ~50-variant catalogue spanning Article, How-to / Recipe, Review, Announcement (Event, JobPosting, Course, Product, ...), Profile (Movie, Book, MusicAlbum, ...), and List families.
Pages have a simpler 5-variant pageType enum: WebPage (default), AboutPage, ContactPage, LearningResource, MedicalWebPage — picked from a dropdown on the page editor.
The create-time wizard (Posts)
When you click New post, the wizard opens with three steps (max — Step 3 may be skipped):
- Pick intent. Six high-level cards: Story, How-to, Review, Announcement, Profile, List. Hit Skip at any step to ship as a plain
BlogPosting. - Narrow within the intent. A grid of sub-types relevant to the intent picked in Step 1 (e.g. Story → BlogPosting / Article / NewsArticle / TechArticle / ScholarlyArticle / Report; How-to → HowTo / Recipe; etc.).
- (Optional) Wrap with a media format. If your post is fundamentally a video or audio piece on top of the chosen type, wrap with
VideoObjectorAudioObject. Most posts skip this step.
All 50+ variants are reachable in ≤3 taps. Pick the closest match — Clog's content authors don't need to know Schema.org. Hover any card for a one-line description.
The chosen type is editable later via a "Change type" button on the post editor. Switching preserves overlapping structuredData fields; field-loss is surfaced in a confirmation modal before commit.
Smart suggestions
For posts that defaulted to BlogPosting (clicked Skip), a banner appears on the editor when Clog detects strong signals for a richer type:
| Signal | Suggested type |
|---|---|
| Title starts with "How to" or "Guide" or "Tutorial" | HowTo |
| Title matches "recipe", "cook", "bake", "how to make" | Recipe |
| Title matches "review", "hands-on", "tested", "verdict" | Review |
| Body contains an FAQ block | FAQPage |
| Body contains a video embed block | VideoObject |
| Category name contains "news" | NewsArticle |
| Title starts with "Top N", "Best N", or a leading number | ItemList |
Click the banner to switch types in one step, or Dismiss to ignore (per-post; the same signal won't surface again on this post).
Post details — structured content
Posts with a non-trivial schemaType get a Post details section in the editor. The fields depend on the type:
- HowTo / Recipe — step list, ingredients, prep / cook / total time, yield, nutrition, cuisine, diet, keywords.
- Event family — start / end date, location (Place or VirtualLocation), organizer, performer, offers.
- Product / Review — brand, SKU, GTIN, MPN, offers, aggregate rating, item reviewed, review rating.
- JobPosting — hiring organization, job location, base salary, employment type, validThrough.
- LocalBusiness / Restaurant / Hotel / Store — address, telephone, openingHours, priceRange, geo coordinates.
- Movie / TVSeries / Book / MusicAlbum — director, actor, ISBN, by-artist, episode/season numbers, etc.
This data is content, not metadata. It serves consumers three ways from one source:
| View | Where it appears | What it's for |
|---|---|---|
| Typed payload | structuredData field on the post response | Consumers building a custom widget — e.g. a Recipe ingredients side-card |
| Reader-render blocks | structuredBlocks (derived on read) | Consumer renders a recipe card / how-to list with the same block renderer it uses for the body — no bespoke per-type code |
| Crawler JSON-LD | jsonLd (derived on read) | Drop into <script type="application/ld+json"> for search engines |
Edit it once, get all three. See API → Rendering content and API → SEO and JSON-LD for the integrator's view.
Type-specific SEO overrides
The General tab's Schema overrides sub-section lets you override structuredData values for crawlers only. Example: shorten step names in seo.schemaData.step for richer SERP snippets while leaving the rendered recipe card untouched. Empty fields fall through to the underlying structuredData — overriding one step doesn't blank the rest.
The live score engine
The Post editor's SEO drawer has an Analysis tab with two scores out of 100: SEO and Readability. Both recompute as you type. Scores are also persisted on save and exposed on the Posts list page so you can sort and filter by them.
SEO checks (12)
Each check returns good / ok / bad:
| Check | Passes when |
|---|---|
| Focus keyword set | The General tab's focus keyword is non-empty. |
| Focus keyword in title | The keyword appears in the meta title (or post title if not overridden). |
| Focus keyword in slug | The slug contains the keyword. |
| Focus keyword in first paragraph | The first paragraph block contains the keyword. |
| Focus keyword in subheadings | At least one H2/H3/H4 contains the keyword. |
| Keyword density 0.5–2.5% | Keyword occurrence rate within the body sits in range. |
| Title length | Meta title is 50–60 chars (40–70 = ok). |
| Description length | Meta description is 120–160 chars (80–180 = ok). |
| Internal links present | At least one link to another /<your-domain>/... URL. |
| External links present | At least one outbound link. |
| Images present | The body contains at least one image block. |
| Alt-text coverage | Every image block has non-empty alt text. |
Readability checks (12)
| Check | Passes when |
|---|---|
| Total word count | ≥ 300 words. |
| First paragraph present | The post opens with a paragraph, not a heading or image. |
| Flesch reading ease | Score ≥ 60. |
| Sentence avg length | Average ≤ 20 words. |
| Long-sentence ratio | ≤ 25% of sentences exceed 25 words. |
| Paragraph max length | No paragraph exceeds 150 words. |
| Subheading distribution | At least one heading per ~300 words. |
| Passive voice | ≤ 10% of sentences are passive. |
| Transition words | ≥ 30% of sentences use a transition. |
| Consecutive sentence starts | No 3+ sentences in a row begin the same way. |
| Intro length | First paragraph ≤ 100 words. |
| Heading hierarchy | Every H3/H4 follows an H2 (no skipped levels). |
Click any check in the Analysis tab to jump to the part of the post that's failing — typing more, breaking a long sentence, adding alt text — and watch the score recover live.
The scores are persisted as seoScore and readabilityScore on the post and surface on the Posts list page. You can sort by them (orderBy=seoScore) or filter on a minimum (minSeoScore) — useful for finding all posts under 80 that need a pass before quarter-end.
Workspace SEO defaults
Open Settings → SEO defaults (in the workspace sidebar, under Settings). This page configures defaults that apply to every content entity unless overridden per-entity. Editing requires both settings:write and seo:write.
Three tabs:
Site & defaults
| Field | What it drives |
|---|---|
| Site name | The %sitename% template variable. Falls back to the workspace name when blank. |
| Site URL | The canonical base URL of your consumer site (e.g. https://example.com/blog). Used by the score engine to classify "internal" vs "external" links and by JSON-LD assembly. |
| Default locale | A BCP-47 code (en, en-US, de-DE). Stamped on JSON-LD payloads. |
| Title separator | The %sep% template variable. Default: —. |
| Default title template | The pattern for the meta title when an entity doesn't override it. Default: %title% %sep% %sitename%. Variables: %title%, %sitename%, %sep%, %category%, %tag%, %author%, %date%, %excerpt%, %page%. Click a chip in the help line to insert; Backspace removes the chip to the left. |
| Default meta description template | Same idea for descriptions. Default: %excerpt%. |
| Default OG image | A media-library image used as og:image when an entity has no per-entity OG image. |
| Default robots | Sitewide robots block, same shape as the per-entity robots field. Per-entity overrides win. |
| Breadcrumbs enabled | When on, JSON-LD payloads include a BreadcrumbList node. |
| Default post type | Pre-selects the type wizard's default for new posts (typically BlogPosting). |
Social
| Field | What it drives |
|---|---|
| Twitter / X site handle | @your-site. Stamped as twitter:site site-wide. |
| Facebook app ID | Used by Open Graph for richer Facebook embeds. |
Publisher & verification
The Publisher section configures the Organization (or Person) node embedded as publisher in every JSON-LD payload — what search engines treat as the entity that owns the content.
| Field | Notes |
|---|---|
| Publisher type | Organization (default), NewsMediaOrganization, NGO, EducationalOrganization, or Person. |
| Name | Publisher's display name. |
| Logo / Photo | A media-library image. For organizations this is a logo; for Person publishers, a photo. |
| Job title (Person only) | e.g. Founder & Editor. |
| Founded / Founder / Telephone / Contact email | Optional. |
| Address | Structured (street, city, region, postal code, country). |
| Same-as URLs | Profile URLs for the publisher (Twitter, GitHub, Wikipedia, ...). |
The Site verification section stores codes for search-console verification:
| Field | Stamped where on your site |
|---|---|
<meta name="google-site-verification" content="..."> | |
| Bing | <meta name="msvalidate.01" content="..."> |
| Yandex | <meta name="yandex-verification" content="..."> |
<meta name="p:domain_verify" content="..."> | |
| Baidu | <meta name="baidu-site-verification" content="..."> |
The codes come back on GET /external/workspace for consumer sites to stamp. They're stored only — Clog doesn't call the search consoles for you.
What an integrator gets
Briefly, so editors know what's going out — full detail lives on the API → SEO and JSON-LD page:
- Every content read response carries the
seometa group as a typed JSON object. - Posts also carry
schemaType,structuredData, the derivedstructuredBlocks, andseoScore/readabilityScore. - A pre-assembled
jsonLdfield on every content read response — drop into<script type="application/ld+json">to ship structured data to crawlers in one round-trip. GET /external/workspacereturns the publisher Organization + site verification codes + default OG image URL for site-wide<head>injection.
Where to next
- Posts — the SEO drawer and Post details section in context.
- Redirects — what to do when changing a slug. Slug changes auto-create 301 redirects.
- API → SEO and JSON-LD — the integrator's view of everything authored here.