12 KiB
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(GitHubLarryWalkerDEV/odoo-expertos, deploys to Vercelwww.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.htmlfiles + 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
- Each workstream (W#) is a self-contained
/goal. Most are parallel-safe (disjoint files). Respect the dependency notes. - 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).
- Each workstream ends by running its Verify and ticking Review. Orchestrator runs
REVIEW.ps1to confirm ALL fixes landed before the goal is done. - 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 <a> 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.
- On-site (automatable now) -
REVIEW.ps1reproduces the checks (building blocks already inraw/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. - 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