Root Cause Analysis Report: Production-Grade SEO & Authority Building
Root Cause Analysis Report: Production-Grade SEO & Authority Building
Jekyll + GitHub Pages Personal Site Optimization
Date: 2026-01-04 Site: https://camilo-cf.github.io/ Engineer: Staff+ Jekyll/SEO Specialist Status: INCIDENT-STYLE ROOT CAUSE ANALYSIS - Required before implementation
Executive Summary
The site has solid i18n infrastructure (EN/ES-419/PT-BR), basic SEO plugins (jekyll-seo-tag, jekyll-sitemap), and spam-safe contact patterns. However, seven critical issues prevent it from being production-grade for positioning Camilo as a reference in ML/AI/DS/MLOps/GenAI:
CRITICAL ISSUES (P0)
- SEO Snippet Mismatch — Google shows outdated “Mechatronic Engineer… PhD student” instead of “Staff ML Engineer & AI Architect”
- Redirect Stubs Unpolished — Legacy
/cv/,/about_me/show bare redirect pages (bad UX, questionable SEO) - Missing Authority Features — No Speaking/Media Kit, no Impact page, no lead magnets
- Outdated Talks Archive — Only 2012-2017 talks visible; no “book me” CTA or current speaking credentials
- Template Incoherence — Publication pages show generic academic template; doesn’t match modern AI brand
- No Persona Routing — Welcome page lacks hiring/engineering/speaking persona CTAs
- Meta Description Staleness — Some pages lack locale-specific descriptions; OG images missing
ISSUE 1: SEO Snippet Mismatch (Critical)
What Google Shows vs What Site Says
Current State (as of 2026-01-04):
- Google SERP for homepage and /cv/: “Mechatronic Engineer focused on mechatronics, AI, and assistive robotics. PhD student of Mechatronics from UNICAMP”
Actual site description (_config.yml line 15): “Staff ML Engineer & AI Architect (Data Science Expert) leading GenAI, MLOps, and applied data science at scale Ph.D. in Mechanical Engineering (Mechatronics) from UNICAMP EMBA (Strategic Leadership)”
Why the Mismatch Exists:
Google Cache Staleness: The site description was recently updated (likely within the last 30-90 days based on commit history), but Google hasn’t re-crawled and re-indexed the pages yet.
- Meta Description Priority: Google’s snippet selection hierarchy:
- Meta description tag (if present and relevant)
- OpenGraph description
- First paragraph of content
- Schema.org description
- Current Meta Implementation:
- File:
_includes/head.htmlline 5 uses `
- File:
` tag from jekyll-seo-tag plugin
- File:
_includes/seo.htmlexists but appears to be legacy (custom implementation) - File:
_includes/seo_schema.htmlhas JSON-LD Person schema with correct description - Plugin Behavior:
jekyll-seo-taggenerates meta description from:page.description(frontmatter)- OR
page.excerpt(frontmatter) - OR
site.description(_config.yml line 15)
- Per-Page Frontmatter Audit:
/en/index.mdline 9:excerpt: "Production ML, causal measurement for ads, MLOps, and GenAI in one place."✓ Good/en/cv/(_pages/cv.md): No explicitdescriptionor custom excerpt; relies on site.description fallback/about_me/(_pages/about_me.md): No frontmatter description; uses old narrative in content
Root Causes:
- RC1: Old content indexed before recent site description update
- RC2:
/about_me/page content starts with old narrative (“Mechatronic Engineer… PhD student”) which Google may prefer over site.description - RC3: No explicit per-page meta descriptions in frontmatter for critical pages (CV, About)
- RC4: No active sitemap resubmission or search console ping after description update
Evidence Files
_config.ymlline 15 (current description: ✓ correct)_pages/about_me.mdline 10 (starts with outdated narrative: ✗ problem)_pages/cv.md(no explicit description: ⚠ relying on fallback)_includes/seo_schema.htmlline 12 (schema description: ✓ correct, uses site.description)
Fix Approach (Priority 1)
- Immediate: Add explicit
descriptionfrontmatter to critical pages:/en/index.md(already has good excerpt ✓)_pages/cv.md→ Add:description: "Staff ML Engineer & AI Architect with production GenAI, MLOps, and causal ads experience"_pages/about_me.md→ Add description + rewrite first paragraph
- Force Re-Crawl: Submit sitemap to Google Search Console after deploy
- Add OpenGraph: Ensure
jekyll-seo-taggenerates og:description (verify in HTML output) - Monitor: Use Google Search Console to track snippet updates (typically 2-7 days after re-crawl)
Risk: Very low - additive only, no breaking changes Impact: High - fixes primary brand positioning issue
ISSUE 2: Redirect Stub Pages Unpolished
Current State
Redirect Mechanism:
- Plugin:
jekyll-redirect-from(GitHub Pages compatible, line 354 in _config.yml) - How it works: Generates HTML pages at old URLs with
<meta http-equiv="refresh">tags pointing to new URLs
Current Redirect Mappings:
/cv/→/en/cv/(defined in_pages/cv.mdline 10)/about_me/→ (no explicit redirect defined; page exists at/about_me/with old content)/contact/→/en/contact/(defined in_pages/contact.mdline 10)/resume/→/en/cv/(defined in_pages/cv.mdline 11)
What Users See: When visiting /cv/ or /contact/, the jekyll-redirect-from plugin generates a bare HTML page:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="0; url=/en/cv/">
<link rel="canonical" href="/en/cv/">
</head>
<body>
<p>Redirecting...</p>
</body>
</html>
Problems:
- Bare UX: No site header, footer, or branding during redirect
- SEO Ambiguity: While
<link rel="canonical">is present, the redirect page itself could be indexed if Google is slow to process the redirect - No Language Preservation:
/cv/redirects to/en/cv/always, even if user came from Spanish or Portuguese context
Why This Exists
- Historical: Site migrated from single-language structure to locale-based URLs
- Good Practice: Using redirects to preserve old URLs (prevents 404s)
- Plugin Limitation:
jekyll-redirect-fromgenerates minimal HTML by default; doesn’t use site layout
Root Causes
- RC1: Plugin default template is intentionally minimal (not a bug, design choice)
- RC2: No custom redirect template implemented to brand the interim page
- RC3: No locale detection/preservation logic in redirect mappings
Evidence Files
_pages/cv.mdline 9-11 (redirect_from definitions)_pages/contact.mdline 9-10 (redirect_from definitions)- Plugin docs: https://github.com/jekyll/jekyll-redirect-from (default template is minimal)
Fix Approach (Priority 2)
Option A: Custom Redirect Template (Recommended)
- Create
_layouts/redirect.htmlwith:- Site header (simplified, logo + tagline)
- “Taking you to the new location…” message
- Meta refresh + canonical (preserve existing)
- Optional: JavaScript redirect with locale detection
- Site footer (minimal)
- Configure
jekyll-redirect-fromto use custom layout (if plugin supports, else use Option B)
Option B: Client-Side Smart Redirect (Fallback)
- Create custom redirect pages manually (e.g.,
/cv/index.html) - Use JavaScript to:
- Detect browser language
- Redirect to matching locale version (/en/cv/, /es-419/cv/, /pt-br/cv/)
- Fallback to /en/ if no match
- Show branded loading state during redirect
Option C: Noindex Redirect Pages
- Keep current minimal redirect pages
- Add
<meta name="robots" content="noindex,follow">to redirect pages - Ensures Google doesn’t index the redirect stubs
Recommended: Option B (smart redirect) + Option C (noindex) for best UX and SEO
Risk: Low - redirect pages aren’t critical content, failures gracefully degrade to working redirects Impact: Medium - improves polish and brand consistency
ISSUE 3: Where Meta Description / OG / Schema Are Defined
Current Implementation Architecture
Layer 1: Jekyll SEO Tag Plugin (Primary)
- File:
_includes/head.htmlline 5: `
`
- Plugin:
jekyll-seo-tag(line 355 in _config.yml) - What it generates:
<title>tag<meta name="description">- OpenGraph tags (og:title, og:description, og:url, og:type)
- Twitter Card tags (twitter:card, twitter:title, twitter:description)
- Canonical link (
<link rel="canonical">)
- Data Sources (priority order):
page.descriptionorpage.excerpt(frontmatter)- Falls back to
site.description(_config.yml line 15) - For og:image:
page.header.imageorsite.og_image(_config.yml line 80, currently empty)
Layer 2: Custom SEO Schema (JSON-LD)
- File:
_includes/seo_schema.html(included in head.html line 7) - What it generates: Person schema with:
- name, jobTitle, description (from site.author and site.description)
- sameAs links (LinkedIn, GitHub, Google Scholar)
- alumniOf, knowsAbout fields
- Status: ✓ Correctly implemented, uses updated site.description
Layer 3: Legacy Custom SEO Include (Unused?)
- File:
_includes/seo.html(exists but NOT included in head.html) - Status: ⚠ Potentially obsolete; verify if any layouts include it directly
- Contents: Custom meta tag generation (likely redundant with jekyll-seo-tag)
Layer 4: Hreflang Links
- File:
_includes/hreflang_links.html(included in head.html line 6) - What it generates:
<link rel="alternate" hreflang="...">tags for language variants - Status: ✓ Correctly implemented, uses translation_targets helper
Layer 5: Config Defaults
- File:
_config.yml- Line 15:
description(site-wide default) ✓ Updated correctly - Line 80:
og_image(currently empty) ✗ Missing - Lines 83-90:
social(Person schema links) ✓ Correct
- Line 15:
Why It’s Stale
Problem 1: Missing Per-Page Descriptions
- Most pages rely on site.description fallback
- Generic site description isn’t optimized for specific page types (CV vs About vs Home)
- Result: Google may ignore generic descriptions and extract from content instead
Problem 2: No OG Images
site.og_imageis empty (line 80)- No per-page og:image definitions
- Result: Social media shares show no preview image; Twitter cards are “summary” type instead of “summary_large_image”
Problem 3: Outdated Content Indexed
- Old pages (/about_me/) have outdated narrative in content
- Even with correct meta tags, Google may prefer content snippets over meta descriptions
/about_me/page starts with “Mechatronic Engineer… PhD student” (line 10) which Google indexes
Problem 4: No Description in Locale Variants
/es-419/index.mdand/pt-br/index.mdmay not have locale-specific descriptions- Falls back to English site.description
Evidence Files
_includes/head.htmllines 5-8 (SEO stack)_includes/seo.html(legacy, not in use)_includes/seo_schema.html(JSON-LD, correct)_config.ymlline 80 (og_image: empty)_pages/about_me.mdline 10 (outdated content)
Fix Approach (Priority 1)
- Add per-page descriptions to all critical pages:
- CV, About, Home (all locales)
- Pillar hubs, Case study index
- Format:
description: "40-160 chars, focus on value + keywords"
- Add OG images:
- Create default:
/images/og-default.jpg(1200x630px, branded) - Add to _config.yml:
og_image: "/images/og-default.jpg" - Optional: Per-page og:image via
header.imagefrontmatter
- Create default:
- Rewrite /about_me/ first paragraph:
- Current: “I’m a Staff ML Engineer… [old narrative]”
- New: Lead with current role, then progression
- Audit locale-specific descriptions:
- Verify
/es-419/index.mdhas Spanish description - Verify
/pt-br/index.mdhas Portuguese description
- Verify
Risk: Very low - additive frontmatter + config changes Impact: High - fixes SEO snippet mismatch and social sharing
ISSUE 4: What Pages Are Being Indexed Unintentionally
Current Indexing State (Hypotheses)
Potentially Over-Indexed:
- Legacy redirect stubs:
/cv/,/contact/,/resume/(if Google hasn’t processed redirects) - Old talks archive:
/talks/shows only 2012-2017 conference papers (outdated authority signal) - Old about_me narrative:
/about_me/with mechatronics-focused content (dilutes modern AI brand) - Publication pages: Individual
/publications/YYYY-MM-DD-title/pages (academic template, may not match brand) - Teaching pages:
/teaching/(if exists) with old content - Language selector pages: Root
/(x-default welcome page) - should be indexed with correct hreflang - Blog filter states:
/en/blog/?category=foo(if using query params, not an issue with current implementation)
Correctly Indexed (Should Stay):
/en/,/es-419/,/pt-br/(locale homepages)/en/pillars/,/en/case-studies/(modern content)/en/cv/,/en/about/(canonical locale versions)- Blog post permalinks
How to Verify
Check Current Index:
site:camilo-cf.github.io
site:camilo-cf.github.io/talks/
site:camilo-cf.github.io/publications/
site:camilo-cf.github.io/cv/
site:camilo-cf.github.io/about_me/
Expected Results:
/cv/should redirect to/en/cv/or show canonical tag (may still be in index if redirect is recent)/talks/should be indexed BUT needs update to modern speaking page/about_me/should redirect to/en/about/(verify if redirect is configured)
Root Causes
RC1: Legacy Content Not Migrated
- Old talks (2012-2017) are in
_talks/collection - No modern speaking/media kit page exists
- Navigation links to
/talks/(line 4 in _pages/talks.html)
RC2: No Noindex on Redirect Stubs
- Redirect pages generated by
jekyll-redirect-fromdon’t have<meta name="robots" content="noindex,follow"> - Google may index them before processing redirect
RC3: About_me Not Redirecting
_pages/about_me.mdhaspermalink: /about_me/(line 2)- Has
redirect_from: /about_me.html(line 5) but doesn’t redirect TO anywhere - Page exists with old content, no redirect to
/en/about/
RC4: Publications Use Generic Template
_publications/collection uses single.html layout- Shows academic template with comments, share buttons
- Doesn’t match modern AI/ML brand narrative
Evidence Files
_pages/talks.html(shows old talks only)_talks/collection (2012, 2013, 2017 papers)_pages/about_me.md(exists, no redirect, old content)_config.ymllines 239-252 (collections config)
Fix Approach (Priority 2)
Action 1: Fix /about_me/ Redirect
# _pages/about_me.md frontmatter
redirect_to: /en/about/ # Add this
# OR delete the file and add redirect_from to _pages/about.md
Action 2: Create Modern Speaking Page
- Create
/en/speaking/index.md(new) - Create
/es-419/charlas/index.md(new) - Create
/pt-br/palestras/index.md(new) - Content: Talk proposals, bio, headshot, “book me” CTA
- Update
/talks/to redirect to/en/speaking/OR keep as archive with link to new speaking page
Action 3: Noindex Legacy Pages (Option A)
# _pages/talks.html frontmatter
title: "Talks Archive (2012-2017)"
robots: noindex,follow # Add this
Action 3: Redirect Legacy Pages (Option B - Recommended)
# _pages/talks.html
redirect_to: /en/speaking/
Action 4: Update Navigation
- Replace “Talks” with “Speaking” in navigation.yml
- Point to
/en/speaking/instead of/talks/
Risk: Low - redirect/noindex changes, no content deletion Impact: Medium - improves brand coherence, removes outdated authority signals
ISSUE 5: Missing Authority-Building Features
Current State vs Required
MISSING (Must Implement):
1. Speaking / Media Kit Page
- Status: ✗ Does not exist
- Current: Only
/talks/archive with 2012-2017 academic papers - Required:
/en/speaking/,/es-419/charlas/,/pt-br/palestras/with:- 4-6 talk proposals (title, abstract, audience, duration)
- Bio (short/medium/long)
- Headshot assets
- “Book me” CTA
- Recent appearances section
2. Impact / Proof of Outcomes Page
- Status: ✗ Does not exist
- Required:
/en/impact/(+ locales) with:- 5 quantified outcomes (sanitized)
- Links to 2-3 case studies
- CTA: speaking, hiring, contact
3. Lead Magnet / Resources
- Status: ✗ No lead magnets
- Current: Blog exists but no gated content
- Required: At least 1 resource page:
- Example: “Ads ML Systems at Scale – Checklist”
- Format: Ungated (trust-building) or email-gated (list-building)
4. Newsletter Page (Locale-Specific)
- Status: ⚠ Partial -
/newsletter/exists but no locale versions - Files:
/newsletter/index.mdexists (line 266 in file listing) - Missing:
/en/newsletter/,/es-419/newsletter/,/pt-br/newsletter/ - Required: Locale-specific pages with:
- Value proposition above fold
- RSS link prominent
- Email signup (Substack embed OR link)
- Localized copy
5. Persona Routing on Welcome Page
- Status: ✗ Not implemented
- Current:
_pages/home.md(root/) shows language selection only - Required: Add persona routing AFTER language selection on locale homepages:
- “Hiring” → /en/cv/ + top case studies
- “Engineering” → /en/pillars/
- “Speaking” → /en/speaking/
Why This Matters
For Hiring Managers:
- Need proof of impact (quantified outcomes)
- Need case studies (already exist ✓)
- Need clear CV (exists ✓)
For Peers:
- Need technical depth (pillars exist ✓)
- Need credibility signals (publications exist ✓, but need modern framing)
- Need contact/collaboration path (exists ✓)
For Conference Organizers:
- CRITICAL GAP: No speaking page, no talk proposals, no bio kit
- Current
/talks/shows 2012-2017 academic papers (outdated, wrong signal) - No “book me” CTA or speaking topics listed
Root Causes
RC1: Site Evolved from Academic Template
- Originally based on AcademicPages Jekyll theme
- Focused on publications/teaching, not modern ML leadership
- Speaking = past conference papers, not forward-looking talk proposals
RC2: No Conversion Funnel Strategy
- Blog exists but no lead magnets
- Newsletter exists but not localized or prominently featured
- No persona-based routing (hiring vs speaking vs engineering)
RC3: Privacy-First Approach (Good) Without Conversion Optimization
- Contact page has spam-safe email (✓ correct)
- But no scheduling link, no “book me” for speaking
- No frictionless paths for different personas
Evidence Files
_pages/home.md(welcome page, no persona routing)_pages/talks.html(archive only, no media kit)/newsletter/index.md(exists but not localized)- Navigation.yml (no speaking link)
Fix Approach (Priority 1 - Required for Spec)
Must Implement:
- Create Speaking Pages (EN/ES/PT) - See detailed spec in deliverables
- Create Impact Page (EN/ES/PT) - See detailed spec in deliverables
- Add Persona Routing to Locale Homepages - Not root
/, but/en/,/es-419/,/pt-br/ - Localize Newsletter Pages - Create
/en/newsletter/, etc. - Create 1 Lead Magnet Page - Example: “Ads ML Systems Checklist”
Implementation Priority:
- Week 1: Speaking pages (highest gap for conference organizers)
- Week 1: Impact page (hiring managers)
- Week 2: Persona routing (UX improvement)
- Week 2: Newsletter localization (conversion)
- Week 3: Lead magnet (optional, nice-to-have)
Risk: Low - new pages, no breaking changes Impact: Critical - unlocks conference/speaking opportunities, improves hiring positioning
ISSUE 6: Template Incoherence (Publications)
Current State
Publications Collection:
- Files:
_publications/*.md(academic papers) - Layout: Uses
single.htmllayout (line 295-302 in _config.yml defaults) - Template Features:
- Author profile sidebar ✓
- Share buttons (Twitter, Facebook, LinkedIn)
- Comments (Giscus enabled, line 26-38 in _config.yml)
- Generic CTA block (“Continue the conversation”)
- Related posts (if enabled)
Problem:
- Academic publications are framed with blog-style social sharing and comments
- CTA block is generic (“Subscribe to newsletter, see case study”) - not contextual
- Doesn’t match modern AI/ML brand narrative
- Feels like academic blog posts, not professional portfolio pieces
Why This Exists
RC1: Inherited from AcademicPages Theme
- Default publication layout was designed for academic blogs
- Assumes readers want to comment/discuss papers
- Share buttons optimized for academic Twitter
RC2: No Custom Publication Layout
- Currently uses generic
single.html(same as blog posts) - No publication-specific layout exists
RC3: Generic CTA on Every Page
_layouts/single.htmlline 76-77: `
Continue the conversation
Need a sounding board for ML, GenAI, or measurement decisions? Reach out or follow along with new playbooks.
`
- Applies to publications, blog posts, pages, case studies
- Not contextually relevant
Evidence Files
_config.ymlline 295-302 (publications defaults)_layouts/single.htmlline 76-77 (CTA inclusion)_includes/post_cta.html(generic CTA content)
Fix Approach (Priority 3 - Polish)
Option A: Custom Publication Layout
- Create
_layouts/publication.html(extends single.html) - Override:
- Remove comments section (publications don’t need discussion)
- Custom CTA: “See how this research applies to production ML” → link to related pillar
- Muted share buttons (keep LinkedIn, remove Facebook)
- Add “Citation” box (BibTeX, APA)
- Update
_config.ymlline 296:layout: publication
Option B: Contextual CTA System
- Create
_includes/cta_publication.html - Update
single.htmlto detect page.collection: ```liquid
Continue the conversation
Need a sounding board for ML, GenAI, or measurement decisions? Reach out or follow along with new playbooks.
**Recommended:** Option B (contextual CTA) - more flexible, applies to talks/teaching too
**Risk:** Low - layout changes, no data migration
**Impact:** Medium - improves brand coherence, reduces CTA fatigue
---
## ISSUE 7: Cookie Banner UX (Minor)
### Current State
**Cookie Consent Implementation:**
- **File:** `_includes/cookie_banner.html`
- **Config:** `_config.yml` lines 133-141
- **Message:** "This site uses cookies… Ads and analytics stay off until you accept."
- **Current Choice Display:** Shows "Current choice: denied" (debug-like text)
**Problem:**
- "Current choice: denied" reads like debug output
- Creates compliance noise (correct behavior, but poor UX)
- Banner is functional but not polished
### Why This Exists
**RC1: Debug Text Left in Production**
- Likely added during development to verify consent state
- Forgot to remove or polish before deploy
**RC2: Compliance-First, UX-Second**
- Correctly implements GDPR/privacy requirements ✓
- But UX polish is lacking
### Evidence Files
- `_includes/cookie_banner.html` (check for "Current choice" text)
- `assets/js/consent.js` (if exists, verify it's updating banner state)
### Fix Approach (Priority 4 - Nice-to-Have)
**Quick Fix:**
1. Remove "Current choice: denied" text from banner
2. Show banner only if consent not yet given (hide after accept/reject)
3. Optional: Add small status indicator in footer ("Privacy settings") instead of inline banner text
**Better Fix:**
1. Move consent status to footer: "Privacy settings: Minimal cookies | Change"
2. Hide banner entirely after user makes choice
3. Allow re-opening banner via footer link
**Risk:** Very low - UX polish only
**Impact:** Low - minor polish, doesn't affect functionality
---
## Summary: SEO & Metadata Architecture
### Where Things Are Defined (Map)
| Component | File | Status | Priority to Fix |
|-----------|------|--------|-----------------|
| Site-wide description | `_config.yml` line 15 | ✓ Correct | - |
| Per-page description | Page frontmatter `description:` | ⚠ Missing on most pages | P1 |
| OG image (default) | `_config.yml` line 80 | ✗ Empty | P1 |
| OG image (per-page) | Page frontmatter `header.image:` | ⚠ Not used | P2 |
| Meta tags (auto) | `<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>Root Cause Analysis Report: Production-Grade SEO & Authority Building | Camilo Andrés Cáceres Flórez</title>
<meta name="generator" content="Jekyll v3.10.0" />
<meta property="og:title" content="Root Cause Analysis Report: Production-Grade SEO & Authority Building" />
<meta name="author" content="Camilo Andrés Cáceres Flórez" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="Staff ML Engineer & AI Architect (Data Science Expert) leading GenAI, MLOps, and applied data science at scale Ph.D. in Mechanical Engineering (Mechatronics) from UNICAMP EMBA (Strategic Leadership)" />
<meta property="og:description" content="Staff ML Engineer & AI Architect (Data Science Expert) leading GenAI, MLOps, and applied data science at scale Ph.D. in Mechanical Engineering (Mechatronics) from UNICAMP EMBA (Strategic Leadership)" />
<link rel="canonical" href="https://camilo-cf.github.io/docs/root-cause-report/" />
<meta property="og:url" content="https://camilo-cf.github.io/docs/root-cause-report/" />
<meta property="og:site_name" content="Camilo Andrés Cáceres Flórez" />
<meta property="og:type" content="website" />
<meta name="twitter:card" content="summary" />
<meta property="twitter:title" content="Root Cause Analysis Report: Production-Grade SEO & Authority Building" />
<meta name="twitter:site" content="@camilocaceresf" />
<meta name="twitter:creator" content="@Camilo Andrés Cáceres Flórez" />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"WebPage","author":{"@type":"Person","name":"Camilo Andrés Cáceres Flórez"},"description":"Staff ML Engineer & AI Architect (Data Science Expert) leading GenAI, MLOps, and applied data science at scale Ph.D. in Mechanical Engineering (Mechatronics) from UNICAMP EMBA (Strategic Leadership)","headline":"Root Cause Analysis Report: Production-Grade SEO & Authority Building","publisher":{"@type":"Organization","logo":{"@type":"ImageObject","url":"https://camilo-cf.github.io/images/Foto_Camilo_perfil.jpg"},"name":"Camilo Andrés Cáceres Flórez"},"url":"https://camilo-cf.github.io/docs/root-cause-report/"}</script>
<!-- End Jekyll SEO tag -->
` in head.html | ✓ Working | - |
| JSON-LD schema | `_includes/seo_schema.html` | ✓ Correct | - |
| Hreflang tags | `_includes/hreflang_links.html` | ✓ Correct | - |
| Canonical tags | `jekyll-seo-tag` (auto) | ✓ Working | - |
| Sitemap | `jekyll-sitemap` plugin | ✓ Generates /sitemap.xml | - |
| Robots.txt | `/robots.txt` | ✓ Exists | - |
| Redirect stubs | `jekyll-redirect-from` | ⚠ Unpolished | P2 |
| Legacy seo.html | `_includes/seo.html` | ⚠ Unused? | P3 (verify/delete) |
### What's Being Indexed (Hypothesis)
**Should Be Indexed:**
- ✓ `/en/`, `/es-419/`, `/pt-br/` (locale homes)
- ✓ `/en/cv/`, `/en/about/`, `/en/pillars/`, `/en/case-studies/`
- ✓ Blog posts (`/en/blog/YYYY/MM/DD/title/`)
- ✓ Root `/` (x-default with hreflang)
**Should NOT Be Indexed (Fix Required):**
- ✗ `/cv/`, `/contact/`, `/resume/` (redirect stubs) → Add noindex
- ✗ `/about_me/` (old content) → Redirect to `/en/about/`
**Needs Update (Content Refresh):**
- ⚠ `/talks/` (2012-2017 archive) → Redirect to `/en/speaking/` OR add "Archive" notice + link to speaking page
- ⚠ Individual publication pages → Polish template, contextual CTA
---
## Implementation Roadmap
### PHASE 0: Root Cause Complete ✓
- This document
### PHASE 1: Critical SEO Fixes (Week 1)
**PR #1: SEO Snippet Mismatch + Meta Descriptions**
1. Add `description` frontmatter to:
- `_pages/cv.md`
- `_pages/about.md`
- `/en/index.md` (already has excerpt, verify)
- `/es-419/index.md`, `/pt-br/index.md`
2. Rewrite `_pages/about_me.md` first paragraph OR redirect to `/en/about/`
3. Add OG default image: `/images/og-default.jpg`
4. Update `_config.yml` line 80: `og_image: "/images/og-default.jpg"`
5. Submit sitemap to Google Search Console
**PR #2: Redirect Polish + Noindex**
1. Add noindex to redirect stubs (custom redirect layout OR manual)
2. Fix `/about_me/` redirect
3. Test all legacy URLs redirect correctly
### PHASE 2: Authority Features (Week 2)
**PR #3: Speaking / Media Kit Pages**
1. Create `/en/speaking/index.md` with:
- 4-6 talk proposals
- Bio (short/medium/long)
- Headshot link
- "Book me" CTA
2. Create `/es-419/charlas/index.md` (localized)
3. Create `/pt-br/palestras/index.md` (localized)
4. Update navigation.yml: Replace "Talks" with "Speaking"
5. Update `/talks/` to redirect OR show "Archive (2012-2017) | See current speaking topics"
**PR #4: Impact Page**
1. Create `/en/impact/index.md` with:
- 5 quantified outcomes
- Links to case studies
- CTA: speaking + hiring + contact
2. Create `/es-419/impacto/index.md` (localized)
3. Create `/pt-br/impacto/index.md` (localized)
### PHASE 3: Conversion Optimization (Week 3)
**PR #5: Persona Routing + Newsletter**
1. Add persona routing to `/en/index.md`, `/es-419/index.md`, `/pt-br/index.md`:
- Hiring → CV + case studies
- Engineering → Pillars
- Speaking → Speaking page
2. Create `/en/newsletter/index.md` (localized)
3. Create `/es-419/newsletter/index.md` (localized)
4. Create `/pt-br/newsletter/index.md` (localized)
**PR #6: Lead Magnet (Optional)**
1. Create `/en/resources/ads-ml-checklist/index.md`
2. Add to navigation or pillar CTAs
### PHASE 4: Template Polish (Week 4)
**PR #7: Contextual CTAs**
1. Create `_includes/cta_publication.html`
2. Create `_includes/cta_speaking.html`
3. Create `_includes/cta_case_study.html`
4. Update `_layouts/single.html` to use contextual CTAs
**PR #8: Cookie Banner Polish**
1. Remove debug text
2. Add footer privacy settings link
### PHASE 5: CI & Testing (Week 5)
**PR #9: Playwright Tests**
1. Setup Playwright
2. Add quality gate tests:
- Welcome page has persona routing ✗ (after PR #5)
- `/en/speaking/` exists with ≥3 talk proposals ✗ (after PR #3)
- `/en/contact/` email not in HTML ✓ (already implemented, verify)
- `/robots.txt` exists ✓
- `/sitemap.xml` exists ✓
3. Add to `.github/workflows/ci.yml`
**PR #10: README + Docs**
1. Update README with:
- Local dev instructions
- How to add new talk/post in all locales
- Cookie consent gating for embeds
2. Document persona routing customization
---
## Appendix: File Locations Reference
### Critical Files for SEO
_config.yml # Site description (line 15), og_image (line 80) _includes/head.html # SEO stack (seo tag, hreflang, schema) _includes/seo_schema.html # JSON-LD Person schema _includes/hreflang_links.html # Language variant tags _includes/seo.html # Legacy (verify if used)
_pages/cv.md # Add description frontmatter _pages/about.md # Add description frontmatter _pages/about_me.md # Redirect to /en/about/ OR rewrite
/en/index.md # Verify excerpt/description /es-419/index.md # Add description /pt-br/index.md # Add description
/robots.txt # ✓ Exists /sitemap.xml # ✓ Auto-generated by jekyll-sitemap
### Files to Create
/en/speaking/index.md # Media kit /es-419/charlas/index.md # Localized /pt-br/palestras/index.md # Localized
/en/impact/index.md # Proof of outcomes /es-419/impacto/index.md # Localized /pt-br/impacto/index.md # Localized
/en/newsletter/index.md # Conversion /es-419/newsletter/index.md # Localized /pt-br/newsletter/index.md # Localized
/images/og-default.jpg # 1200x630px OpenGraph image
_layouts/redirect.html # Custom redirect template (optional) _includes/cta_publication.html # Contextual CTA _includes/cta_speaking.html # Contextual CTA _includes/cta_case_study.html # Contextual CTA
.github/workflows/ci.yml # CI with Playwright tests/smoke.spec.js # Playwright tests playwright.config.js # Playwright config ```
END OF ROOT CAUSE REPORT
Next Steps:
- Review this report with stakeholder (Camilo)
- Prioritize PRs based on business goals (conference speaking = prioritize PR #3)
- Begin Phase 1 implementation
- Measure: Google Search Console snippet updates, social share previews, speaking inquiries
Approval Required Before Proceeding to Implementation.
Continue the conversation
Need a sounding board for ML, GenAI, or measurement decisions? Reach out or follow along with new playbooks.
