Files
our-claude-skills/custom-skills/95-ourdigital-presales-seo/SKILL.md
Andrew Yim 6f69a6a484 Route estimate outputs to central archive (ourdigital-space/estimates)
All estimates now archive to ~/Workspaces/ourdigital-space/estimates/
<YYYY-MM-DD>_<prospect|account>_<service>/ (single 견적 archive). Engine
SKILL.md documents the output-home convention (engine stays --out-dir-agnostic).
presales-seo Stage 5 writes the estimate to $EST (archive); Stage 6 deck reads
from $EST but stays in the engagement bundle.

(Workspace side, not in this repo: SHR estimate moved to the archive, pointer
left in the engagement, ourdigital-space/CLAUDE.md documents estimates/.)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 02:22:33 +09:00

7.0 KiB
Raw Blame History

name, description
name description
ourdigital-presales-seo Standardized pre-sales SEO + Knowledge Graph diagnostic for a prospect domain that produces a technical/on-page scan, KG/entity analysis, consolidated brief, a rate-card-based cost estimate (견적), and an editable PPTX sales deck. Use for pre-sales prospecting, sales briefing prep, "pre-sales SEO audit", "프리세일즈 진단", "견적 + 제안 슬라이드", or when preparing for a prospect meeting. Public-data only (no client GSC/GA4 access required). Korean-first output.

OurDigital Pre-sales SEO Workflow

Runs the full pre-sales diagnostic for any prospect domain as step-by-step confirmed stages, ending in a cost estimate and a sales-briefing deck. Public-data only — designed for prospects where you don't yet have GSC/GA4/GTM access.

Origin: standardizes the Sono Hotels & Resorts pre-sales diagnostic.

Execution model — STEP BY STEP

Run one stage at a time. After each stage, present the result and WAIT for the user's go-ahead before the next. Create a TodoWrite/Task item per stage. Stages 5 (estimate) and 6 (deliverables) are explicit review gates — never send without sign-off.

Stage 0 — Scope & preflight

Collect (ask only for what you can't infer):

  • domain (required); brand_name + aliases (앤/& / EN variants — infer from <title>/og first)
  • sub_brands, properties (auto-extract from crawl URL patterns in Stage 1 if not given)
  • competitors (else pick a set from references/competitor_sets.md by vertical)
  • market/language (default South Korea / ko), vertical
  • output_dir — default routing: if ~/Workspaces/<slug>-workspace/ exists → …/audits/<YYYY-MM-DD>-presales/, else ~/Workspaces/seo-workspace/prospecting/<YYYY-MM-DD>-<prospect>/

Preflight tool check (report missing + fallback): Firecrawl, DataForSEO, GOOGLE_KG_API_KEY, headless Chrome, python-pptx. Create data/ subfolder. Initialize findings.json (see findings.schema.json).

Stage 1 — Discovery & crawl

  • WebFetch robots.txt + /sitemap.xml + /sitemap_index.xml (note status; 500/404 = finding).
  • firecrawl_map (limit high, includeSubdomains) → URL inventory; record discoverable_urls, derive URL architecture, estimated_pages, and hygiene flags (/test, params, duplicate path schemes).
  • Populate findings.json.discovery. → write scan §1.

Stage 2 — Technical / on-page

  • firecrawl_scrape (json) homepage + 1-2 property pages: JSON-LD @types, Organization completeness (sameAs/alternateName/address), meta/title/H1, hreflang set, robots/googlebot meta.
  • mcp__dfs-mcp__on_page_lighthouse homepage (+ a property) → CWV.
  • Populate findings.json.technical. → write 01_technical-onpage-scan.md.
  • Honesty rule: never claim "noindexed" if the page ranks — flag conflicting directives as "verify".

Stage 3 — Knowledge Graph / entity

  • python scripts/kg_query.py --brand … --aliases … --parent … --legacy … --subbrands … --properties … --competitors … --out-dir <out>/data (needs GOOGLE_KG_API_KEY; run with sandbox disabled — read-only API GET).
  • Live SERP panel verification: mcp__dfs-mcp__serp_organic_live_advanced (ko, South Korea) for brand, a sub-brand, a property, and one competitor → record actual panel type/title, local packs, reseller leakage.
  • Populate findings.json.entity (panel, name_split, legacy_contamination, sub-brand/property entity counts, competitor_benchmark[], wikipedia). → write 02_knowledge-graph-entity.md + data/serp_panels_findings.md.

Stage 4 — Consolidated brief

  • Synthesize, rank by severity, build the competitive-gap table. Populate findings.json.findings[]. → write 03_presales-opportunity-brief.md.

Stage 5 — Estimate (견적) — REVIEW GATE

Pricing is delegated to the ourdigital-estimate-engine skill (../96-ourdigital-estimate-engine). Estimates are archived centrally in OurDigital's space, not in the engagement bundle:

  • EST=~/Workspaces/ourdigital-space/estimates/<YYYY-MM-DD>_<account_code>_seo — create it (central 견적 archive).
  • python scripts/findings_to_scope.py --findings <out>/data/findings.json --out "$EST/data/scope.json" --seq <N> [--tier auto|smb|basic|treatment] [--billing 0.70]
  • ENG=../96-ourdigital-estimate-engine; python $ENG/scripts/estimate.py --rate-card $ENG/references/rate_card.yaml --catalog-dir $ENG/catalog --scope "$EST/data/scope.json" --out-dir "$EST"
  • Engine (effort method, seo catalog): auto-tier (smb/basic/treatment) by portfolio + premium-vertical floor; On-page hours scale by subbrands_total (cap ×2.0); 제안가 = 합계 절사. Reproduces Basic ₩10.5M / Treatment ₩25.0M; SMB ~₩3M; 25-property chain ~₩29.5M.
  • Produces 05_estimate_ko.md, 05_estimate.xlsx, data/estimate.json in $EST (the central quote archive; effort shape → consumed by build_deck.py). Present the 견적; get sign-off.
  • SEO findings→scope/tier mapping lives here (findings_to_service.md); rates/hours/tiers live in the engine (rate_card.yaml + catalog/seo.yaml) — edit pricing there, not here.

Stage 6 — Deliverables — REVIEW GATE before send

  • Client PDF: author the short brief HTML from templates/client_brief.html (fill the content; keep the CSS), then bash scripts/render_pdf.sh <brief>.html → PDF. Verify Korean renders (Read the PDF).
  • Sales deck: python scripts/build_deck.py --findings <out>/data/findings.json --estimate "$EST/data/estimate.json" --out <out>/sales-deck.pptx (deck stays in the engagement bundle; reads the archived estimate.json from $EST)
  • Sanitize the client-facing pieces: no internal pricing strategy beyond the 견적; tasteful competitor benchmark only.

Stage 7 — Archive (standard)

Push the consolidated report to the OurDigital SEO Audit DB:

python <notion-writer path>/notion_writer.py \
  --database 2c8581e5-8a1e-8035-880b-e38cefc2f3ef \
  --title "<프로스펙트> SEO 사전진단 (Pre-sales) — <YYYY-MM-DD>" \
  --properties '{"Target URL": "<domain>", "Audit Date": "<YYYY-MM-DD>", "Account Code": "<CODE>"}' \
  --file <out>/03_presales-opportunity-brief.md

Property names are exact: Target URL, Audit Date, Account Code. Do NOT set Audit ID (read-only formula). notion-writer path: ~/Project/our-claude-skills/custom-skills/32-notion-writer/code/scripts/notion_writer.py.

Tool gotchas (learned)

  • OurSEO crawl_website caps ~60 pages regardless of max_pages — use Firecrawl map for inventory; report the discoverable count as a finding.
  • Firecrawl scrape cache may return empty — re-scrape.
  • KG API + headless Chrome + Notion push need network → run those Bash calls with the sandbox disabled.
  • Korean PDF: headless Chrome uses system fonts (AppleSDGothicNeo on macOS). On Windows set deck font to Malgun Gothic in build_deck.py.

Conventions

  • Korean-first for all client-facing output; keep technical terms in English (SEO, CWV, Schema, hreflang).
  • File names: 01_/02_/03_/05_ prefixes as above; raw artifacts in data/.
  • Outputs go to the workspace (Stage 0 routing), never into this skills repo.