Skip to Content
Content ToolkitSEO Brief Export & Collaboration

SEO Brief Export & Collaboration

[To Build] · API feature · provider-google OAuth scope addition

Enables content briefs to be shared with external writers via a public link (no login required), exported to Google Docs with one click, and validated against the final blog draft via a brief compliance check.

Related: Content Brief Writer · Blog Writer · Content Toolkit Overview


Overview

FunctionShare, export, and validate SEO content briefs
TypeAPI feature — Collaboration
StatusTo Build
PriorityP2 — Differentiating
Sub-featuresShareable link · Google Docs export · Brief compliance check
Credits0 cr (share/export) · 0.25 cr (compliance check)
PlanFree+ (share link) · Pro+ (Google Docs export + compliance check)

Why This Is Needed

Content briefs are generated by the content-brief-writer agent but live entirely inside Leadmetrics. When a DM agency works with freelance writers or client-side content teams, there is no way to hand off a brief without:

  • Either giving the external writer a Leadmetrics login (a billing and security concern)
  • Or manually copying the brief into a Google Doc or email

Additionally, once a blog post is written against a brief, there is no automated check to confirm the writer actually followed it — keyword coverage, target word count, and required sections may have been missed.


A tokenised public URL that renders the brief in read-only mode. No authentication required.

How It Works

DM clicks "Share" on a content brief API: POST /tenant/v1/content-briefs/:id/share - Generates a signed token: HMAC-SHA256(briefId + tenantId + expiresAt, SECRET_KEY) - Creates BriefShareToken record in DB: { briefId, token, expiresAt, createdBy } - Returns: { shareUrl: "https://app.leadmetrics.io/brief/share/{token}" } External writer opens the URL GET /brief/share/:token (public route, no auth middleware) - Validate token signature + expiry - Render brief in a clean read-only view (no sidebar, no navigation, no editable fields)

Token Rules

PropertyValue
Default expiry30 days
Max expiry90 days
RevocableYes — DM can revoke from brief settings; token is deleted from DB
ScopeSingle brief; token cannot be used to access any other resource
RegenerableYes — “Reset link” creates a new token and invalidates the old one

Brief Share DB Model

model BriefShareToken { id String @id @default(cuid()) briefId String tenantId String token String @unique expiresAt DateTime createdBy String createdAt DateTime @default(now()) brief ContentBrief @relation(fields: [briefId], references: [id], onDelete: Cascade) tenant Tenant @relation(fields: [tenantId], references: [id]) }

Public Brief View

The public brief view at /brief/share/:token renders:

  • Working title + meta description
  • Primary and secondary keywords
  • Search intent
  • Target word count + rationale
  • Recommended outline (H2/H3 structure with notes per section)
  • Internal link targets (as text, not hyperlinks)
  • Tone and style notes
  • Brand voice summary (if a brand voice doc is in the RAG dataset)

It does not render competitor URLs, internal pricing, or any tenant account data.


Sub-Feature 2: Google Docs Export

Pushes the brief content into a new Google Doc in the tenant’s connected Google Drive account. Returns a shareable Google Doc link.

How It Works

DM clicks "Export to Google Docs" on a content brief API: POST /tenant/v1/content-briefs/:id/export/google-docs - Checks ConnectedChannel for Google account with Drive scope - If not connected: returns 400 with message "Connect a Google account with Drive access in Settings → Channels" provider-google: Docs API → documents.create - Creates a new Doc titled: "[Brief] {brief.title} — Leadmetrics" - Populates with structured content (headings, keyword table, outline) - Sets sharing: "anyone with link can comment" - Returns: { googleDocUrl: string, googleDocId: string } Stores googleDocId on ContentBrief record Returns shareUrl to dashboard; DM can copy and send to writer

Google OAuth Scope Addition

Add https://www.googleapis.com/auth/drive.file to the Google OAuth scope in provider-google. This is a narrower scope that only allows access to files created by the app (not the user’s full Drive).

Doc Structure

The generated Google Doc follows this structure:

# [Brief] {title} ## Brief Details | Property | Value | | Primary Keyword | {keyword} | | Secondary Keywords | {keywords} | | Search Intent | {intent} | | Target Word Count | {count} | ## Recommended Outline ### H2: {section title} Notes: {notes} Keywords to include: {keywords} ### H2: {section title} ... ## Tone & Style Notes {notes} ## Internal Link Targets - {page name}: {url} --- Generated by Leadmetrics on {date}

Sub-Feature 3: Brief Compliance Check

After a blog post draft exists, compares the draft against the original brief to produce a BriefComplianceResult.

What It Checks

CheckHow
Primary keyword present in titleExact or fuzzy match
Primary keyword present in bodyAt least 3 occurrences
Secondary keyword coverage% of secondary keywords that appear at least once in body
Word count complianceDraft word count vs brief’s targetWordCount (pass if within ±15%)
Outline section coverage% of brief H2 sections that have a corresponding H2 in the draft
Meta description presentNon-empty, 140–160 chars

Output Contract

interface BriefComplianceResult { blogPostId: string; briefId: string; checkedAt: string; overallPass: boolean; checks: { primaryKeywordInTitle: { pass: boolean; detail: string }; primaryKeywordInBody: { pass: boolean; detail: string }; secondaryKeywordCoverage: { pass: boolean; coveragePercent: number; missing: string[] }; wordCountCompliance: { pass: boolean; draftWordCount: number; targetWordCount: number; delta: number }; outlineSectionCoverage: { pass: boolean; coveragePercent: number; missingSections: string[] }; metaDescriptionPresent: { pass: boolean; detail: string }; }; }

How It Works

DM opens blog post that was generated from a brief API: POST /tenant/v1/content-briefs/:briefId/compliance-check?blogPostId={id} - Heuristic comparison: no LLM call needed - Returns BriefComplianceResult immediately Blog editor sidebar shows compliance panel: - "Brief Compliance" section with pass/fail per check - Overall ✅ / ⚠️ indicator - Specific guidance for each failing check

The compliance check is heuristic (string matching, word count), not LLM-based, so it costs 0.25 cr only for the outline section coverage check (which needs a light LLM pass to do fuzzy H2 matching). A free tier with exact matching only is 0 cr.


New API Routes

MethodPathAuthDescription
POST/tenant/v1/content-briefs/:id/shareTenantGenerate share token; return share URL
DELETE/tenant/v1/content-briefs/:id/shareTenantRevoke share token
GET/brief/share/:tokenNone (public)Render brief in read-only view
POST/tenant/v1/content-briefs/:id/export/google-docsTenantPush brief to Google Docs; return doc URL
POST/tenant/v1/content-briefs/:briefId/compliance-checkTenantRun compliance check against a blog post

Key Design Decisions

DecisionChoiceRationale
HMAC token for share linksHMAC-SHA256(briefId + tenantId + expiresAt)Cryptographically signed; unguessable; verifiable without a DB lookup on every request
Narrow Google Drive scopedrive.file not driveOnly access files created by Leadmetrics; does not request access to the tenant’s full Google Drive
Compliance check is heuristicRule-based string matching, not LLMFast (< 200ms), free, deterministic — covers 90% of usefulness; LLM not needed for counting occurrences
Compliance check placed in brief, not blogPOST /content-briefs/:briefId/compliance-check?blogPostId=The brief is the authority document; the blog is checked against it, not the other way around

Implementation Phases

  1. Add BriefShareToken model to Prisma schema (migration)
  2. Implement POST /tenant/v1/content-briefs/:id/share route — HMAC token generation
  3. Implement GET /brief/share/:token public route — token validation + brief render page
  4. Dashboard brief detail page: “Share” button + copy-link panel + revoke button

Phase 2 — Google Docs Export

  1. Add https://www.googleapis.com/auth/drive.file to Google OAuth scopes in provider-google
  2. Implement createBriefDoc() in provider-google package
  3. Add POST /tenant/v1/content-briefs/:id/export/google-docs route
  4. Store googleDocId on ContentBrief model
  5. Dashboard brief detail page: “Export to Google Docs” button + doc link display

Phase 3 — Brief Compliance Check

  1. Implement BriefComplianceResult type in packages/common
  2. Implement compliance check service in apps/api/src/services/
  3. Add POST /tenant/v1/content-briefs/:briefId/compliance-check route
  4. Blog editor sidebar: “Brief Compliance” panel (shown when blog was generated from a brief)

© 2026 Leadmetrics — Internal use only