From 8df260b90d0d0e8ec5e8ba19f040539122027826 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Sat, 24 Oct 2026 19:00:47 +0000 Subject: [PATCH] Add 12-month growth plan, baseline, weekly log and measurement loop Week-by-week plan grounded in current GSC data (4,745 impressions, 9 clicks, CTR 0.19%, hosting cluster at position 27.5, 1,090 impressions on page-1 zero-click queries). One bounded change per week, measured the following week. Snapshot script: ~/.hermes/scripts/growth_week.py. --- growth/BASELINE.md | 55 +++++++++++++++ growth/PLAN.md | 161 +++++++++++++++++++++++++++++++++++++++++++ growth/WEEKLY-LOG.md | 27 ++++++++ growth/metrics.jsonl | 1 + growth/state.json | 4 ++ 5 files changed, 248 insertions(+) create mode 100644 growth/BASELINE.md create mode 100644 growth/PLAN.md create mode 100644 growth/WEEKLY-LOG.md create mode 100644 growth/metrics.jsonl create mode 100644 growth/state.json diff --git a/growth/BASELINE.md b/growth/BASELINE.md new file mode 100644 index 0000000..765c431 --- /dev/null +++ b/growth/BASELINE.md @@ -0,0 +1,55 @@ +# Baseline — 2026-10-24 + +Captured from the n8n stats webhook before any CRO work. Every later week is compared to +this. Range: 2026-01-01 → 2026-10-24. + +## Search Console (10 months) + +| metric | value | +|---|---| +| queries | 447 | +| impressions | 4,745 | +| clicks | 9 | +| CTR | 0.19% | +| average position | 24.7 | +| queries with ≥10 impressions | 105 | +| of those, on page 1 (pos ≤ 10) | 31 | +| page-1 queries with **zero** clicks | 17, holding 1,090 impressions | + +Clusters: + +| cluster | queries | impressions | clicks | avg position | +|---|---|---|---|---| +| hosting (money) | 33 | 538 | 1 | 27.5 | +| consulting | 11 | 402 | 0 | 50.4 | +| AI | 22 | 555 | 0 | 9.6 | + +Head terms: `odoo hosting` 298 impr / pos 31.5 · `hosting odoo` 85 / 28.5 · +`odoo beratung` 155 / 51.5 · `odo ia` 279 / 6.8 (0 clicks) · +`odoo de donde es` 154 / 5.3 (0 clicks). + +## Plausible + +| metric | value | +|---|---| +| visitors | 2 (both test/owner traffic, week of 2026-10-19) | +| pageviews | 3 | +| goals configured | 1 — page goal `Visit /` | +| affiliate clicks (goal) | not measured yet — custom-event goals not created | + +## Site + +- 1,208 HTML pages across 6 locales (es root, en, de, fr, pt, ar). +- 479 outbound links to odoo4projects.com, all bearing `utm_source=odoo-expertos.com`. +- 12 pages carry the hosting CTA block (6 homepages, 6 hosting hubs). +- 40 near-duplicate `/odoo-hosting/*` pages per locale. +- Known defects: 3 fabricated testimonials, unverifiable ISO 27001 / SOC 2 / "200+ proyectos" + badges, placeholder phone on 8 pages, one 0-byte page in the PT sitemap. + +## How to refresh + +```bash +python3 ~/.hermes/skills/marketing/odoo-expertos-site/scripts/website_stats.py +``` + +Snapshots are appended to `growth/metrics.jsonl` by `~/.hermes/scripts/growth_week.py`. diff --git a/growth/PLAN.md b/growth/PLAN.md new file mode 100644 index 0000000..857874d --- /dev/null +++ b/growth/PLAN.md @@ -0,0 +1,161 @@ +# odoo-expertos.com — 12-month improvement plan + +One change per week. Measure the previous week before starting the next. +North-star metric: **affiliate clicks** (Plausible goal `Affiliate Click`). +Supporting metrics: GSC clicks, money-keyword position, outbound CTR. + +Guiding rules: + +- A week ships **one** bounded change, deployed and verified live, logged in `WEEKLY-LOG.md`. +- Every change states a hypothesis and the metric it should move, **before** it ships. +- Next week starts by reading the result of last week. Keep, revert, or adjust — then move on. +- Impressions are the guardrail: if GSC impressions drop more than 10% week over week, stop + new work and diagnose before continuing. +- No invented proof. No fake testimonials, certifications or client names, ever. + +Baseline (2026-10-24, see `BASELINE.md`): 4,745 impressions, 9 clicks, CTR 0.19%, avg +position 24.7, money cluster at position 27.5, affiliate clicks ≈ 0. + +--- + +## Phase 0 — Instrumentation (week 0) + +Done before the loop starts: Plausible tag on 1,206 pages, `Affiliate Click` / +`Outbound Click` events, UTM on all 479 outbound links, weekly snapshot script, this plan. + +**Week 1 — Product marketing context.** +Write `.agents/product-marketing.md`: ICP, pains, objections, proof, positioning. Every +later copy decision reads from this file. +*Metric:* none (enabler). *Done when:* file exists and is committed. + +--- + +## Phase 1 — Remove what disqualifies us (weeks 2–7) + +**Week 2 — Strip the fabricated proof.** +Remove the three invented testimonials, the ISO 27001 / SOC 2 / "200+ proyectos" badges, and +the placeholder phone number (8 pages). Replace with the real customer list. +*Hypothesis:* E-E-A-T and trust signals improve; removes legal exposure. +*Metric:* no ranking loss (guardrail week), Plausible outbound CTR on those pages. + +**Weeks 3–6 — CTR rescue on page-1 zero-click queries.** +17 queries sit on page 1 with 0 clicks and hold 1,090 impressions (23% of all impressions). +Rewrite title + meta description for 4 landing pages per week, ordered by impressions: +`odo ia` (279), `odoo de donde es` (154), `de donde es odoo` (115), `odoo honduras` (81), +`.odo ia` (66), `odoo origen` (60), `odoobot que es` (56), `docker odoo 20` (32 ×2), +`odoo 20 docker`, `odoo de que pais es` (32), `hosting economicos` (30), `odoo inmobiliaria` +(27), `odoo bot` (25), `odoo de donde es originario` (25). +*Hypothesis:* these positions already earn the impression; the snippet is what fails. +*Metric:* CTR on those queries (target 0.19% → 1.5% site-wide by week 8). + +**Week 7 — Kill the empty page.** +`pt/odoo-ia/odoo-sistema-reservas-booking-ia-2025/` is a 0-byte file in the sitemap that +returns an empty 200. Fill it with the translated ES content or remove it and regenerate the +sitemap. +*Metric:* index coverage. + +--- + +## Phase 2 — Make the money pages worth ranking (weeks 8–19) + +Context: `odoo hosting` = 298 impressions at position 31.5. `hosting odoo` = 85 at 28.5. +The affiliate funnel is correct but nothing reaches it. + +**Weeks 8–10 — Consolidate the thin hosting pages (ES first).** +40 near-duplicate `/odoo-hosting/*` pages per language cannibalize each other. Keep one hub, +keep the 6 genuine country pages, 301 the rest into the closest survivor, regenerate the +sitemap. Do not delete pages that have impressions without checking GSC per URL first. +*Hypothesis:* consolidating authority lifts the hub for `hosting odoo`. +*Metric:* position of `hosting odoo` / `odoo hosting`, hub impressions. + +**Weeks 11–13 — Rebuild the ES hosting hub as a real comparison.** +Actual prices ($214/$395/$595/$950+), what each plan includes, backups, regions, migration +path, who it is wrong for. Comparison table above the fold. `Service` + `FAQPage` schema. +One primary CTA with our UTM. +*Hypothesis:* a page that answers "which plan and why" earns links and converts. +*Metric:* affiliate clicks from `/odoo-hosting/`, position for `odoo hosting`. + +**Weeks 14–16 — Same rewrite for EN, then DE.** +DE matters: `odoo beratung` has 155 impressions at position 51.5 — the German section is +underperforming relative to its size. +*Metric:* per-language affiliate clicks. + +**Weeks 17–19 — Internal links into the money pages.** +Add contextual links from the 50 highest-impression articles to the hosting hub, in the +article's own language. Anchor text describes the destination, not "click here". +*Metric:* hub entry pages, affiliate clicks. + +--- + +## Phase 3 — Content that deserves to rank (weeks 20–30) + +**Weeks 20–23 — Upgrade the top 20 impression pages.** +Add what competitors don't have: screenshots from a real instance, benchmark numbers, +version-specific detail (19 vs 20), "what this costs" sections. +*Metric:* average position and CTR on those 20 URLs. + +**Weeks 24–27 — Article-level CRO.** +Contextual CTA blocks inside articles at natural stopping points, matching the article's +topic (hosting article → hosting CTA; module article → module CTA). No popups. +*Metric:* affiliate clicks per 1,000 sessions; scroll-to-CTA rate. + +**Weeks 28–30 — Contact path.** +The only conversion today is `mailto:`. Replace with a short form (name, email, what they +need) posting to the existing webhook, with a real success state. +*Metric:* form submissions (new goal), goal conversion rate. + +--- + +## Phase 4 — Locale quality (weeks 31–36) + +**Weeks 31–33 — Audit ar/pt/fr.** +Find pages whose main content is untranslated boilerplate. Either translate the body or +`noindex` them. Never cross-locale canonical, never hreflang a page you don't want indexed. +*Metric:* index coverage ratio per locale, locale impressions. + +**Weeks 34–36 — Localise the money pages properly.** +Currency, payment methods, local hosting expectations, local phone/hours where real. +*Metric:* affiliate clicks from non-ES locales. + +--- + +## Phase 5 — Authority (weeks 37–46) + +**Weeks 37–40 — Original data asset.** +Publish "Odoo hosting prices compared" with a method, a date, and a table others can cite. +This is the link magnet; everything else is maintenance. +*Metric:* referring domains, positions for comparison queries. + +**Weeks 41–43 — Directory + OCA presence.** +Submit to relevant directories; get the OCA module tracker listed where Odoo users look. +*Metric:* referring domains, referral sessions. + +**Weeks 44–46 — Outreach round.** +20 personalised pitches to Odoo blogs/communities pointing at the data asset. No bought links. +*Metric:* links earned, referral traffic. + +--- + +## Phase 6 — Scale what works (weeks 47–52) + +**Weeks 47–49 — Template the winner.** +Take the best-converting page structure and apply it to the 6 country pages. +*Metric:* affiliate clicks per country page. + +**Weeks 50–51 — Decay sweep.** +Refresh the 20 posts with falling impressions (update prices, versions, dates). +*Metric:* recovered impressions. + +**Week 52 — Year review.** +Compare every phase against its metric. Kill what didn't work, codify what did into the +templates and into the `odoo-expertos-site` skill. + +--- + +## Weekly loop (what the cron job does) + +1. Snapshot metrics, diff against last week, print the delta. +2. Read last week's log entry: what shipped, what it was supposed to move. +3. Record the verdict: keep / revert / adjust. +4. Take the next week's action from this file, implement it, deploy, verify live. +5. Write the log entry with hypothesis + metric before moving on. diff --git a/growth/WEEKLY-LOG.md b/growth/WEEKLY-LOG.md new file mode 100644 index 0000000..66ffd12 --- /dev/null +++ b/growth/WEEKLY-LOG.md @@ -0,0 +1,27 @@ +# Weekly log + +One entry per week. The hypothesis and the metric are written **before** the change ships; +the measurement is filled in by the following week's run. A week without a measurement is +an unfinished week. + +| Week | Date | Change | Hypothesis | Metric watched | Expected | Measured | Verdict | +|---|---|---|---|---|---|---|---| +| 0 | 2026-10-24 | Instrumentation: Plausible tag on 1,206 pages, `Affiliate Click` / `Outbound Click` custom events, UTM on 479 outbound links, CTA blocks on 6 homepages + 6 hosting hubs, weekly loop installed | Without measurement every change is a guess | all | baseline established | n/a (setup) | keep | + +--- + +## Entry template + +```markdown +### Week N — YYYY-MM-DD + +**Shipped:** +**Hypothesis:** +**Metric:** +**Expected:** + +**Measured (week N+1):** +**Verdict:** keep / revert / adjust — and why + +**Next:** +``` diff --git a/growth/metrics.jsonl b/growth/metrics.jsonl new file mode 100644 index 0000000..ca8405e --- /dev/null +++ b/growth/metrics.jsonl @@ -0,0 +1 @@ +{"ts": "2026-10-24T19:00:18+00:00", "clicks": 9, "impressions": 4745, "ctr": 0.18967334035827188, "position": 24.75, "queries": 447, "page1_zero_queries": 17, "page1_zero_impressions": 1090, "money_impressions": 538, "money_position": 27.5, "visitors": 2, "pageviews": 3, "goals": {"Visit /": 1}} diff --git a/growth/state.json b/growth/state.json new file mode 100644 index 0000000..f700cd4 --- /dev/null +++ b/growth/state.json @@ -0,0 +1,4 @@ +{ + "current_week": 1, + "started": "2026-10-24" +}