# GOAL-DRIVEN FIX PLAN — odoo-expertos.com **For a `/goal` run with parallel agents.** Date: 2026-05-27 · Source of truth: `FULL-AUDIT-REPORT.md` (Part A + Part B). > **Target repo:** `C:\Users\eugen\.cursor\projects\Odoo Expertos\odoo-expertos` (GitHub `LarryWalkerDEV/odoo-expertos`, deploys to Vercel `www.odoo-expertos.com`). > **NOT** the immoapp repo. Agents must work in the Odoo repo and never write to immoapp. > **Codebase:** ~1,210 hand/script-generated static `.html` files + JS components (`components/*.js`) + `templates/pillar-page.html` + `vercel.json` + build scripts. There is **no central page generator**, so most content fixes are **scripted bulk transforms (codemods) over the HTML files** (write a Node/Python codemod, run it over all files, verify, commit). Component/template fixes touch one file and affect all pages that include them. --- ## How to run with /goal + parallel agents 1. Each **workstream (W#)** is a self-contained `/goal`. Most are **parallel-safe** (disjoint files). Respect the dependency notes. 2. Batching: - **Batch 1 (parallel, fast/independent):** W1, W2, W8, W9, W10, W11 - **Batch 2 (parallel codemods):** W3, W4-structure, W5, W6 - **Batch 3 (the big rock, gated):** W7 (localization/consolidation). After W7, re-run W4-final (hreflang reflects surviving pages) then W1-final (regen sitemaps). 3. Each workstream ends by running its **Verify** and ticking **Review**. Orchestrator runs `REVIEW.ps1` to confirm ALL fixes landed before the goal is done. 4. One branch/PR per workstream; nothing merges until its Verify passes. --- ## Baseline metrics (captured 2026-05-27 — compare after fixes) | Metric | Baseline | Target | |---|---|---| | URLs not indexed (GSC) | ~870 / 1,210 (approx 72%) | <15% (after re-crawl, 2-4 wks) | | Crawled-not-indexed | 587 | <100 | | Duplicate (wrong canonical) | 103 | <20 | | Discovered-not-indexed | 134 | <30 | | True 404s | 12 | 0 | | Sitemap URLs that redirect/404/non-canonical | present | 0 | | Category title length | 260-267 chars | <=60 | | Meta descriptions unique | templated/near-dup | 100% unique | | ES articles reachable <=2 clicks | 156 / 193 (37 orphaned) | 193 / 193 | | Homepage H1 word-spacing bug | present (all langs) | fixed | | Homepage visual score | 3/10 | >=8/10 | | Hreflang reciprocity | broken (EN missing pt/ar; DE->404 es) | 100% reciprocal, all 200 | | Schema logo URL | dead domain odooexpertos.com | valid, www | | Security headers | missing 4 | present | --- ## WORKSTREAMS ### W1 - Sitemap & redirect hygiene · parallel-safe (final pass gated on W7) **Problem:** sitemaps list 404s, redirecting URLs, and non-canonical URLs (Part B B0/B3). **Tasks:** (1) Build missing index pages `/en/odoo-hosting/`, `/fr/odoo-hosting/`, `/pt/odoo-hosting/` (mirror DE/AR) OR drop their loc entries if W7 retires them. (2) Remove every sitemap URL that 404s/redirects (country-variant + index.html URLs in vercel.json)/non-canonical. (3) Each loc = exact canonical (www, trailing slash), matching the page canonical tag. (4) Regenerate via `generate_sitemap.sh`. **Files:** `sitemap*.xml`, `generate_sitemap.sh`, `vercel.json`. **Acceptance:** 0 sitemap URLs non-200; every loc == live canonical. **Verify:** `pwsh REVIEW.ps1 -Only W1`. **Review:** [ ] ### W2 - robots.txt cleanup · parallel-safe **Problem:** two `User-agent: *` groups (2nd ignored), duplicate Bingbot/CCBot, meaningless `/*#` (Part A 1). **Tasks:** one group per agent; merge `Disallow: /*?` and `/*&` into the FIRST `User-agent: *`; delete the 2nd `*` block, duplicate Bingbot/CCBot, and the fragment disallow; keep AI-crawler allows + Sitemap line. **Files:** `robots.txt`. **Acceptance:** exactly one `User-agent: *`; query disallows present in it; no fragment disallow; one Bingbot, one CCBot. **Verify:** `pwsh REVIEW.ps1 -Only W2`. **Review:** [ ] ### W3 - Structured data (schema) · parallel-safe (codemod) **Problem:** dead logo domain odooexpertos.com; non-www schema URLs; DE page Spanish schema; Article missing image/mainEntityOfPage; truncated dateModified; duplicate Microdata; empty sameAs; no shared Org @id; missing inLanguage (Part A 3). **Tasks (codemod over all .html + templates/pillar-page.html + components/eeat.js):** (1) replace odooexpertos.com -> www.odoo-expertos.com and all non-www schema url/item -> www. (2) ONE Organization with stable @id, real logo, populated sameAs; reference by @id elsewhere. (3) Article: add absolute image + mainEntityOfPage + valid ISO dateModified; remove duplicate Microdata itemtype. (4) add BreadcrumbList JSON-LD to deep pages; inLanguage per page; translate DE/PT/FR schema strings (coordinate W7). **Files:** bulk `.html`, `templates/pillar-page.html`, `components/eeat.js`. **Acceptance:** Rich Results passes for Organization(logo loads)/Article(image)/Breadcrumb on sample; 0 occurrences of dead domain or non-www JSON-LD. **Verify:** `pwsh REVIEW.ps1 -Only W3`. **Review:** [ ] ### W4 - Hreflang correctness · structure parallel-safe; FINAL pass gated on W7 **Problem:** EN inner pages omit pt+ar; DE inner pages point es/x-default to /de/-prefixed Spanish slugs that 404; category pages have ZERO hreflang (Part A 1). **Tasks (codemod over all .html):** (1) each page emits full hreflang for the languages it actually has, www, all resolving 200, plus x-default -> root ES URL (no /de/ prefix). (2) fix DE: es and x-default hrefs built from the root ES path. (3) add the block to all category index pages. (4) enforce reciprocity; drop hreflang to non-existent variants. **Files:** bulk `.html`, head template. **Acceptance:** 100% reciprocity on sample; every hreflang href 200; category pages have hreflang. **Verify:** `pwsh REVIEW.ps1 -Only W4`. **Review:** [ ] ### W5 - Titles & meta descriptions · parallel-safe (codemod) **Problem:** category titles 260-267 chars (stuffed); templated near-duplicate metas; title==H1; og:locale=es_ES on DE/FR/PT (Part A 2, Part B B0.3). **Tasks (codemod over all .html):** (1) category titles <=60 chars, target-language pattern `[keyword] - [value] | Odoo Expertos`. (2) every meta description UNIQUE (kill the "Guia completa sobre Odoo X con Odoo..." template) generated from real page content. (3) og:locale per language. **Files:** bulk `.html`. **Acceptance:** 0 titles >60; 0 duplicate metas corpus-wide; og:locale matches lang. **Verify:** `pwsh REVIEW.ps1 -Only W5`. **Review:** [ ] ### W6 - Internal linking & crawl depth (<=3 clicks) · parallel-safe (OWNS the JS-nav removal) **Problem:** nav injected client-side via a parser-blocking DOM-write in components/header.js (JS-dependent); 37+ orphaned articles/lang; article bodies have 0 internal links (Part B B1). **Tasks:** (1) render header/footer/eeat as STATIC HTML in every page (replace the createHeader()/createFooter()/createEEAT() injection with baked-in HTML via codemod, or a build-time include); keep the mobile-toggle JS. (2) category hubs link ALL their articles (crawlable `` pagination if needed) -> every article <=2 clicks from a hub. (3) article template: rendered breadcrumb (HTML anchors, not just schema) + parent-category link + >=3 related-article links. (4) add an HTML sitemap page `/mapa-del-sitio/` linked in the footer. **Files:** `components/header.js`/`footer.js`/`eeat.js` (+ bulk .html to inline), category index pages, article template, footer. **Acceptance:** every indexable page <=3 clicks from `/`; nav present in static HTML (no JS); 0 orphans vs sitemap. **Verify:** `pwsh REVIEW.ps1 -Only W6` (re-runs the depth crawler in raw/analyze.py; reachable==total). **Review:** [ ] · **Dep:** owns the JS-nav->static conversion (W10 references it). ### W7 - Content localization & consolidation · THE BIG ROCK · gated, mostly sequential **Problem:** 400+ EN/DE pages serve Spanish/garbled MT (-> 103 duplicate + much of 587 crawled-not-indexed); thin ~400-word bodies (Part A 2 C2, Part B B0). **Tasks (phased - where most of the 870 unindexed pages are won back):** (1) decide per page-cluster: translate properly, OR consolidate duplicates into one strong page, OR noindex + drop from sitemap. Default: ES canonical; keep a language variant only if genuinely translated. (2) properly translate the kept variants; fix garbled hybrids ("Inteligencai Artificail", "ueber", "fuer"). (3) expand surviving thin articles to >=1,200 words of unique useful content. (4) remove fabricated author / "Apex AI Research Labs LLC"; attribute to real author or org. **Files:** bulk `.html` content, author pages. **Acceptance:** declared lang matches content on 100% sample; no MT-hybrid strings; surviving articles >=1,200 words; no fabricated author. **Verify:** `pwsh REVIEW.ps1 -Only W7`. **Review:** [ ] · **Dep:** W4-final + W1-final run AFTER this. ### W8 - Homepage rebuild · parallel-safe **Problem:** visually broken (empty sections, unrendered hero viz), H1 word-spacing bug, combat/fear hype, unsourced 280% ROI (Part B B2, Part A 2 H4). **Tasks:** (1) fix H1 span concatenation so words have spaces ("Para Robarte", "with Odoo", "mit Odoo", "de Inteligencia Artificial para") on all 6 homepages. (2) render hero/section content server-side (remove opacity:0-until-scroll gating or give a visible default); fix/remove the broken D3 hero viz; eliminate empty dark sections. (3) replace combat hype with factual, keyword-led E-E-A-T copy; source or remove "280% ROI"; add Organization JSON-LD (shared @id). (4) re-screenshot desktop+mobile; human re-verify >=8/10. **Files:** `index.html`, `en/index.html`, `de/`, `fr/`, `pt/`, `ar/`, related CSS/JS. **Acceptance:** no run-together words; no empty sections; visual score >=8/10. **Verify:** `pwsh REVIEW.ps1 -Only W8` + manual screenshot review. **Review:** [ ] ### W9 - 404 source fixes · parallel-safe (fast) **Problem:** case-sensitivity (`/odoo-Hosting/`), wrong slug (`/odoo-ai/` vs `/odoo-ia/`), linked-but-missing (`/consultoria-erp`, `.pdf`, `/mes`) (Part B B3). **Tasks:** add lowercase-enforcement + 301s in vercel.json for known capitalized/legacy URLs; pick one of /odoo-ai/ <-> /odoo-ia/ and 301 the other; fix internal links to missing pages or create them. **Files:** `vercel.json`, link sources. **Acceptance:** all 12 GSC 404 URLs return 200 or 301-to-200. **Verify:** `pwsh REVIEW.ps1 -Only W9`. **Review:** [ ] ### W10 - Performance / CWV · parallel-safe (JS-nav removal owned by W6) **Problem:** 32KB inline CSS, runtime D3 from CDN, Cache-Control max-age=0, render-blocking CSS on content pages (Part A 5). **Tasks:** trim homepage inline style to <14KB (rest -> main.min.css); self-host d3.v7.min.js + preload only where used + remove misplaced preconnect; add `Cache-Control: max-age=31536000, immutable` for hashed /css,/js,/components in vercel.json; apply async-CSS + critical-CSS to the content-page template. **Files:** `index.html`, `vercel.json`, `css/`, `templates/pillar-page.html`, `js/`. **Acceptance:** Lighthouse mobile LCP<=2.5s / INP<=200ms / CLS<=0.1 (PSI key); inline CSS <14KB; D3 self-hosted. **Verify:** `pwsh REVIEW.ps1 -Only W10` + `npx lighthouse`. **Review:** [ ] ### W11 - Security headers · parallel-safe (fast) **Tasks:** add to vercel.json headers: `X-Content-Type-Options: nosniff`, `X-Frame-Options: SAMEORIGIN`, `Referrer-Policy: strict-origin-when-cross-origin`. **Acceptance:** headers present on live responses. **Verify:** `pwsh REVIEW.ps1 -Only W11`. **Review:** [ ] --- ## REVIEW - "did every fix land?" After all workstreams, the orchestrator re-measures vs the baseline table. 1. **On-site (automatable now)** - `REVIEW.ps1` reproduces the checks (building blocks already in `raw/analyze.py` + curl probes): W1 sitemap 200+canonical; W2 robots single-group; W3 grep 0 dead-domain/non-www JSON-LD; W4 hreflang reciprocity+200; W5 titles<=60 & metas unique; W6 depth crawler reachable==total & static nav; W7 lang-match + MT-marker grep + word counts; W8 H1 spacing + screenshot >=8/10; W9 the 12 known 404s now 200/301; W10 Lighthouse + inline CSS size; W11 headers. 2. **Off-site (lagging, manual)** - after deploy, in Google Search Console: resubmit sitemaps, "Validate Fix" on each coverage issue, re-export coverage in 2-4 weeks. Target not-indexed <15%. This is the ultimate proof; on-site checks are leading indicators. **Definition of done:** all 11 Review boxes ticked + REVIEW.ps1 all-green + homepage visual >=8/10 + a fresh `seo-audit` re-run >=70/100, with GSC re-validation queued. ## Branch/PR map fix/w1-sitemaps · fix/w2-robots · fix/w3-schema · fix/w4-hreflang · fix/w5-titles-meta · fix/w6-internal-links · fix/w7-localization · fix/w8-homepage · fix/w9-404s · fix/w10-perf · fix/w11-headers