Files
our-claude-skills/custom-skills/95-ourdigital-presales-seo/SKILL.md
Andrew Yim 5f66f57a8e Rebuild estimate engine to effort-based SOW model
Replace flat per-service ranges with OurDigital's real quoting model
(role_rate × billing_rate 0.70 × standard hours), sourced from the
06_Working Template quotes:
- rate_card.yaml: role rate card, billing/basis/terms, tools, scaling bands
- sow_templates.yaml: basic + treatment task-hour templates
- estimate.py: assemble SOW from findings, scale Technical/On-page hours by
  properties_total, 제안가 = 합계 floored to 500k
- build_deck.py: estimate slide shows module 소계 + 제안가 (point)
- findings_to_service.md / SKILL.md / DESIGN.md: synced to new model

Validated: reproduces real Basic ₩10.5M and Treatment ₩25.0M exactly;
SHR (25 properties) scales to ₩71.5M, L'Escape (1) = ₩25.0M.

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

91 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: ourdigital-presales-seo
description: 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 `@type`s, 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
- `python scripts/estimate.py --findings <out>/data/findings.json --rate-card references/rate_card.yaml --sow references/sow_templates.yaml --out-dir <out> --seq <N> [--baseline basic|treatment] [--billing 0.70]`
- **Effort-based** (OurDigital real model): cost = role_rate × 청구율 70% × 표준 업무시간, by module; 제안가 = 합계 절사. findings auto-select baseline (basic/treatment) and scale Technical/On-page hours by `properties_total`.
- Produces `05_estimate_ko.md`, `05_estimate.xlsx`, `data/estimate.json`. Present the 견적; get sign-off.
- Logic in `references/findings_to_service.md`; rates/hours in `rate_card.yaml` + `sow_templates.yaml` (edit together). Reproduces real Basic ₩10.5M / Treatment ₩25.0M quotes.
## 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 <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_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.