Blog best practices
Every released blog from Essel runs through ten agents that enforce a specific quality bar — researched from Google’s helpful-content guidance, Ahrefs, Backlinko, Semrush, Yoast, and HubSpot, and then encoded as binding rules in our prompt contracts. This page explains what the system optimizes for, how to brief it well, and what the draft is guaranteed to be — and not be.
What the system optimizes for
Five principles, in priority order:
- Helpful content first. Google’s helpful-content system explicitly punishes pages that “leave the reader wanting” or “summarize what others have to say without adding much value.” Every draft must answer the query directly within the first 60 words and include at least one piece of original information (a number, named source, dated example, or quote) that competing pages don’t already publish.
- Match the SERP format. If 8 of the top 10 results for a keyword are listicles, the article ships as a listicle. If they’re definitions, it leads with one. The keyword research and outline agents both diverge from the dominant SERP angle — they don’t default to a house format.
- Front-load relevance. The primary keyword appears in the H1, the first 100–150 words of the body (exactly once, naturally), and at least one H2. The title itself is held to a 50–60 character band with the keyword in the first half — the position correlates with rank.
- Differentiate, don’t mirror. When competitors are configured, the planner pulls each competitor’s top organic keywords from SEMrush, computes the content gaps (keywords competitors rank for that the workspace hasn’t covered), and biases topic selection toward those gaps. The draft is forbidden from paraphrasing a top SERP page’s angle.
- Trust signals over volume. No fluff intros, no “in conclusion”
closers, no AI-tell phrases (
delve,navigate the landscape,it's important to note, etc.). The revision agent strips these on every pass regardless of whether the quality reviewer flagged them.
How to brief the system
Target keywords
The first entry of targetKeywords is treated as the locked primary
keyword — the keyword research agent doesn’t second-guess it unless
it’s wildly off the prompt. The remaining entries become mandatory
secondary keywords that must each appear naturally in the prose; if
the draft can’t honestly include one, it surfaces the omission in reviewerNotes rather than silently dropping it.
The system fetches a real SEMrush overview (search volume, keyword difficulty, search intent, CPC) for each entry and feeds those metrics into the keyword research prompt — so editor-supplied keywords get ranked against actual demand, not just brand intuition.
Competitors
Configured competitor domains drive two layers of intelligence:
- Per competitor, the system pulls the top 8 organic keywords (by
traffic share) via SEMrush
domain_organic. The keyword research and cadence planner both see this list and use it to shape the differentiator angle. - Across the workspace, the planner computes a content-gap list: competitor keywords minus titles already released in the workspace. The cadence planner prefers gap keywords as primary-keyword candidates so the editorial calendar fills holes the editor didn’t have to find manually.
We cap competitor expansion at three domains and eight keywords each per fetch — enough to bias the planner without burning SEMrush budget.
Word limit
wordLimit is a soft target with a ±10% band, not a hard cap. The
draft agent treats it as the editor’s intended length and tightens scope
accordingly. Defer to SERP medians per intent type when you’re unsure:
| Intent | Typical SERP median | When to override |
|---|---|---|
| Informational guide | 2,100–2,400 words | Set lower if the topic is genuinely narrow |
| Commercial / “best X” / comparison | 1,200–1,500 words | Higher only when comparing 5+ products in depth |
| Narrow how-to | 600–900 words | Don’t pad below the SERP norm |
Setting wordLimit on a cadence propagates to every blog scheduled
out of it — useful for keeping a publishing programme to a consistent
length without setting it per-post.
What the agents enforce
Each agent owns a slice of the quality bar. When you debug an output, the table tells you which step to look at:
| Agent | Enforces |
|---|---|
keyword_research | Format-matches the SERP, keeps editor-supplied keywords as primary + mandatory secondaries, flags cannibalization with existing workspace titles |
title_strategy | 50–60 char title band, keyword front-loaded, positive sentiment, one CTR modifier max, never mirrors a top SERP title verbatim |
outline | One H1, contiguous heading levels, paragraph-zero TL;DR per section, FAQ phrasing mirrors PAA verbatim, list-type discipline (ordered for “how to”, unordered for “types of”) |
draft | Primary keyword in first 100–150 words, ≥ 3 different non-paragraph elements per 1000 words, AI-tell phrases banned, no fluff intros, no “in conclusion” closers, summary-of-others prose rejected |
metadata | Slug ≤ 5 words with stopwords stripped and no dates, meta description as ad copy with [value]. [detail+keyword]. [CTA] shape, alt text describes content + relationship in ≤ 125 chars |
quality_review | “Left wanting” test, AI-tell scan, sloppy-quality flag, markdown-too-plain detection (markdown-too-plain issue code) |
plagiarism_review | SERP-angle-overlap detection, paraphrase-of-competitor flagging |
revision | Standing scrub-list applied every revision: AI-tell phrases, fluff intros, “in conclusion” closers, repetitive section openers — even when the reviewer didn’t flag them |
cadence_research / cadence_planner | Content-gap-aware topic selection, distributes editor-supplied keywords across topics, never silently drops a supplied keyword |
What the draft delivers
The markdown payload returned by GET /api/consumer/blogs/{blogId} is GitHub-Flavored Markdown with a richness budget. Every long-form
draft uses at least three of:
- Tables for comparisons, criteria matrices, pros/cons (capped at 5×8).
- Callout-style blockquotes —
> **Note:** …,> **Tip:** …,> **Warning:** …,> **Example:** …. 0–3 per article; portable across every CommonMark renderer. - Pull-quote blockquotes for genuine third-party quotes, always with attribution. Never invented.
- Fenced code blocks with language tags for any snippet a reader might copy.
- Ordered lists for steps; unordered lists for types/examples.
- Task lists (
- [ ]/- [x]) for checklists the reader walks through. - GFM footnotes (
[^1]) for inline citations. - Bold first-mention of key terms.
A 1500+ word draft with zero of these elements gets flagged with markdown-too-plain (severity: major) and bounced back to the
revision agent.
Anti-patterns the system rejects
If you see one of these in an output, it slipped past the reviewer — file it, because the contracts forbid them:
- Fluff intros: “In today’s fast-paced world…”, “Have you ever wondered…”, dictionary-definition openers, restating the H1 as the first sentence. The intro should answer the query directly.
- AI-tell phrases:
delve,tapestry,navigate the landscape,unleash the power,game-changer,in the realm of,embark on a journey,it's important to note. Pattern-matched and scrubbed on every revision. - Curiosity-gap clickbait titles that withhold the answer (“The one thing nobody tells you about X”). Google’s scaled-content policy explicitly punishes “pages that pretend to have answers but fail to deliver.”
- Summary-of-others prose: rewriting the top 3 SERP results without adding original specifics. Every long-form draft must include at least one number, named source, dated example, direct quote, or walkthrough that competitors don’t already publish.
- Wall-of-text drafts: long-form articles built only from H2s, paragraphs, and images.
- Decorative callouts with no actionable content. Every callout must change what the reader does next.
- Faked quotes. Either the quote is real and attributable, or the block is dropped.
- Padded word count: writing past
wordLimitwith restatement. Tighter sections beat repetition.
Cadence-level scoring
When a cadence proposal is generated, every topic carries a commercial-potential score (0–100) derived from its keyword’s SEMrush metrics:
| Component | Weight |
|---|---|
| Search volume (log-scaled) | 40% |
| Keyword difficulty (inverted) | 25% |
| Search intent (transactional/commercial > informational) | 20% |
| CPC (log-scaled — proxy for buyer intent) | 15% |
Topics with strong volume + healthy KD + commercial intent score ≥ 65 (“strong”); ≥ 40 is “ok”; below is “weak.” Editors approve by ROI signal rather than gut. Scores are recomputed on regeneration but not on manual keyword edits — flag a topic for re-proposal if you want a fresh score.
What’s still on you
The system can’t fake what it doesn’t have access to. To get the most out of it:
- Brand notes with proprietary specifics. The single biggest
E-E-A-T lever is concrete information competitors don’t publish —
internal numbers, customer scenarios, named studies, screenshots.
Put them in the workspace’s
defaultModelPolicy.brandNotesso every draft can lift them. - Author bylines and
dateModified. Google’s helpful-content guidance names byline + author profile linkage as required for credibility. Today the API returnsfrontmatterandreleasedAt; wire them into the byline + last-updated stamp on your rendered page. - Internal links between released blogs. The current draft agent
doesn’t write internal links; once a
internal_linkingworkflow step lands it will, but for now plumb a related-articles block on your end keyed offrenderedSlugandtags. - Real competitor data. The richer the competitor list per workspace and per cadence, the better the gap analysis. Three well-chosen domains beats ten approximate ones.
Sources
This page draws from:
- Google: Creating helpful, reliable, people-first content
- Google: SEO Starter Guide
- Google: March 2024 core update and spam policies
- Ahrefs: SEO Writing, Featured Snippets, Keyword Cannibalization
- Backlinko: On-Page SEO, Google CTR Stats
- Semrush: SEO Writing
- Yoast: Meta Descriptions, Image SEO
- HubSpot: Blog SEO
- Grow and Convert: Pain Point SEO