Files
2026-08-28 10:11:11 -03:00

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 (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 <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.

  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