New skill 96-ourdigital-estimate-engine: method-aware quoting engine (effort / coaching / procurement) with universal rate_card + per-service catalog. Real catalogs: seo (effort), education (coaching); stubs: digital_ads, digital_branding. Validated to reproduce real quotes — SEO basic ₩10.5M / treatment ₩25.0M, SHR chain ₩29.5M, L'Escape basic ₩10.5M, GA4/GTM coaching ₩1,570,000, procurement +15%. Refactor 95-ourdigital-presales-seo: remove rate_card.yaml, sow_templates.yaml, estimate.py (migrated to engine); add findings_to_scope.py; Stage 5 now maps findings→scope.json and calls the engine CLI. build_deck/kg_query unchanged; end-to-end validated on SHR (29.5M) + deck renders engine estimate.json. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6.8 KiB
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 fromreferences/competitor_sets.mdby vertical)market/language(default South Korea / ko),verticaloutput_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
WebFetchrobots.txt +/sitemap.xml+/sitemap_index.xml(note status; 500/404 = finding).firecrawl_map(limit high, includeSubdomains) → URL inventory; recorddiscoverable_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_lighthousehomepage (+ a property) → CWV.- Populate
findings.json.technical. → write01_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(needsGOOGLE_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). → write02_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[]. → write03_presales-opportunity-brief.md.
Stage 5 — Estimate (견적) — REVIEW GATE
Pricing is delegated to the ourdigital-estimate-engine skill (../96-ourdigital-estimate-engine); this skill only maps findings → scope, then calls the engine:
python scripts/findings_to_scope.py --findings <out>/data/findings.json --out <out>/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 <out>/data/scope.json --out-dir <out>- Engine (effort method,
seocatalog): auto-tier (smb/basic/treatment) by portfolio + premium-vertical floor; On-page hours scale bysubbrands_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(effort shape → consumed bybuild_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), thenbash 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 <out>/data/estimate.json --out <out>/sales-deck.pptx - 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_websitecaps ~60 pages regardless ofmax_pages— use Firecrawlmapfor inventory; report the discoverable count as a finding. - Firecrawl
scrapecache 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 indata/. - Outputs go to the workspace (Stage 0 routing), never into this skills repo.