All posts
General7 min read

Odoo website SEO: meta tags, JSON-LD structured data, sitemap, and page speed

Odoo Website includes SEO tools for meta titles, descriptions, and XML sitemaps, but most structured data and Core Web Vitals optimization requires custom QWeb template overrides. Here is what works out of the box and what you must build.

Odoo's website module includes basic SEO controls, but "basic" is accurate: per-page meta title and description editing, a generated sitemap, and an Open Graph image. Structured data (JSON-LD), canonical URLs, hreflang tags, and Core Web Vitals optimization all require custom work. Here is a realistic picture of what Odoo handles automatically versus what you build.

What Odoo Website includes by default#

Per-page SEO editor:

Each website page, blog post, product page, and event page has an SEO panel (visible in the website editor: Promote → Search Engine Optimization). Fields:

  • Title (populates </code> and OG title)</li><li>Description (populates <code class="bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono"><meta name="description"></code> and OG description)</li><li>Keywords (not used by modern search engines; can be ignored)</li></ul><p class="text-slate-600 leading-relaxed my-4 text-sm"><strong>XML sitemap:</strong></p><p class="text-slate-600 leading-relaxed my-4 text-sm">Automatically generated at <code class="bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono">/sitemap.xml</code>. Includes:</p><ul class="list-disc list-inside space-y-2 text-slate-600 my-4 text-sm leading-relaxed"><li>All published website pages.</li><li>All published products (if eCommerce is enabled).</li><li>All published blog posts.</li><li>All events.</li></ul><p class="text-slate-600 leading-relaxed my-4 text-sm">The sitemap updates when content publishes. Submit it to Google Search Console.</p><p class="text-slate-600 leading-relaxed my-4 text-sm"><strong>Robots.txt:</strong></p><p class="text-slate-600 leading-relaxed my-4 text-sm">Generated at <code class="bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono">/robots.txt</code>. Points to the sitemap. Configurable in Website → Configuration → Settings → SEO → Robots.txt.</p><p class="text-slate-600 leading-relaxed my-4 text-sm"><strong>Open Graph tags:</strong></p><p class="text-slate-600 leading-relaxed my-4 text-sm">OG tags (<code class="bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono">og:title</code>, <code class="bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono">og:description</code>, <code class="bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono">og:image</code>) are populated from the SEO editor fields. OG image requires the page to have a cover image set.</p><h2 id="adding-json-ld-structured-data" class="group text-xl font-bold text-slate-900 mt-10 mb-4 scroll-mt-20"><a href="#adding-json-ld-structured-data" class="no-underline">Adding JSON-LD structured data<span class="ml-2 opacity-0 group-hover:opacity-100 transition-opacity text-slate-400 font-normal text-sm">#</span></a></h2><p class="text-slate-600 leading-relaxed my-4 text-sm">Odoo does not generate JSON-LD for products, blog posts, or events automatically. Add it via QWeb template inheritance.</p><p class="text-slate-600 leading-relaxed my-4 text-sm"><strong>Product schema (Product page):</strong></p><div class="relative group/code my-6"><span class="absolute top-2 left-4 text-xs font-mono text-slate-400 select-none">xml</span><button aria-label="Copy code" class="absolute top-2 right-2 hidden group-hover/code:flex items-center gap-1 px-2 py-1 rounded text-xs font-medium bg-slate-700 text-slate-300 hover:bg-slate-600 transition-colors"><svg class="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M15.666 3.888A2.25 2.25 0 0013.5 2.25h-3c-1.03 0-1.9.693-2.166 1.638m7.332 0c.055.194.084.4.084.612v0a.75.75 0 01-.75.75H9a.75.75 0 01-.75-.75v0c0-.212.03-.418.084-.612m7.332 0c.646.049 1.288.11 1.927.184 1.1.128 1.907 1.077 1.907 2.185V19.5a2.25 2.25 0 01-2.25 2.25H6.75A2.25 2.25 0 014.5 19.5V6.257c0-1.108.806-2.057 1.907-2.185a48.208 48.208 0 011.927-.184"></path></svg>Copy</button><pre class="bg-slate-900 text-slate-100 rounded-lg overflow-x-auto text-sm font-mono pt-8 pb-4 px-4"><code><template id="product_page_jsonld" inherit_id="website_sale.product"> <xpath expr="//head" position="inside"> <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Product", "name": "<t t-esc="product.name"/>", "description": "<t t-esc="product.description_sale or ''"/>", "sku": "<t t-esc="product.default_code or ''"/>", "offers": { "@type": "Offer", "priceCurrency": "<t t-esc="website.currency_id.name"/>", "price": "<t t-esc="product.list_price"/>", "availability": "https://schema.org/InStock" } } </script> </xpath> </template></code></pre></div><p class="text-slate-600 leading-relaxed my-4 text-sm"><strong>Blog post schema:</strong></p><div class="relative group/code my-6"><span class="absolute top-2 left-4 text-xs font-mono text-slate-400 select-none">xml</span><button aria-label="Copy code" class="absolute top-2 right-2 hidden group-hover/code:flex items-center gap-1 px-2 py-1 rounded text-xs font-medium bg-slate-700 text-slate-300 hover:bg-slate-600 transition-colors"><svg class="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M15.666 3.888A2.25 2.25 0 0013.5 2.25h-3c-1.03 0-1.9.693-2.166 1.638m7.332 0c.055.194.084.4.084.612v0a.75.75 0 01-.75.75H9a.75.75 0 01-.75-.75v0c0-.212.03-.418.084-.612m7.332 0c.646.049 1.288.11 1.927.184 1.1.128 1.907 1.077 1.907 2.185V19.5a2.25 2.25 0 01-2.25 2.25H6.75A2.25 2.25 0 014.5 19.5V6.257c0-1.108.806-2.057 1.907-2.185a48.208 48.208 0 011.927-.184"></path></svg>Copy</button><pre class="bg-slate-900 text-slate-100 rounded-lg overflow-x-auto text-sm font-mono pt-8 pb-4 px-4"><code><template id="blog_post_jsonld" inherit_id="website_blog.blog_post_complete"> <xpath expr="//head" position="inside"> <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BlogPosting", "headline": "<t t-esc="blog_post.name"/>", "datePublished": "<t t-esc="blog_post.post_date"/>", "author": { "@type": "Person", "name": "<t t-esc="blog_post.author_id.name"/>" } } </script> </xpath> </template></code></pre></div><p class="text-slate-600 leading-relaxed my-4 text-sm">Validate the output at Google's Rich Results Test.</p><h2 id="canonical-urls" class="group text-xl font-bold text-slate-900 mt-10 mb-4 scroll-mt-20"><a href="#canonical-urls" class="no-underline">Canonical URLs<span class="ml-2 opacity-0 group-hover:opacity-100 transition-opacity text-slate-400 font-normal text-sm">#</span></a></h2><p class="text-slate-600 leading-relaxed my-4 text-sm">Odoo adds a <code class="bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono"><link rel="canonical"></code> tag to most pages pointing to the current URL. For product pages accessible via multiple URLs (e.g., category-filtered views), the canonical points to the product's base URL.</p><p class="text-slate-600 leading-relaxed my-4 text-sm">Override the canonical in edge cases:</p><div class="relative group/code my-6"><span class="absolute top-2 left-4 text-xs font-mono text-slate-400 select-none">xml</span><button aria-label="Copy code" class="absolute top-2 right-2 hidden group-hover/code:flex items-center gap-1 px-2 py-1 rounded text-xs font-medium bg-slate-700 text-slate-300 hover:bg-slate-600 transition-colors"><svg class="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M15.666 3.888A2.25 2.25 0 0013.5 2.25h-3c-1.03 0-1.9.693-2.166 1.638m7.332 0c.055.194.084.4.084.612v0a.75.75 0 01-.75.75H9a.75.75 0 01-.75-.75v0c0-.212.03-.418.084-.612m7.332 0c.646.049 1.288.11 1.927.184 1.1.128 1.907 1.077 1.907 2.185V19.5a2.25 2.25 0 01-2.25 2.25H6.75A2.25 2.25 0 014.5 19.5V6.257c0-1.108.806-2.057 1.907-2.185a48.208 48.208 0 011.927-.184"></path></svg>Copy</button><pre class="bg-slate-900 text-slate-100 rounded-lg overflow-x-auto text-sm font-mono pt-8 pb-4 px-4"><code><template id="custom_canonical" inherit_id="website.layout"> <xpath expr="//link[@rel='canonical']" position="replace"> <link rel="canonical" t-attf-href="https://#{website.domain}/products/#{product.id}"/> </xpath> </template></code></pre></div><h2 id="hreflang-for-multilingual-sites" class="group text-xl font-bold text-slate-900 mt-10 mb-4 scroll-mt-20"><a href="#hreflang-for-multilingual-sites" class="no-underline">hreflang for multilingual sites<span class="ml-2 opacity-0 group-hover:opacity-100 transition-opacity text-slate-400 font-normal text-sm">#</span></a></h2><p class="text-slate-600 leading-relaxed my-4 text-sm">If you run Odoo website in multiple languages, search engines need <code class="bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono">hreflang</code> tags to understand which language version to serve in which region. Odoo does not generate these automatically.</p><p class="text-slate-600 leading-relaxed my-4 text-sm">Add them via a controller override:</p><div class="relative group/code my-6"><span class="absolute top-2 left-4 text-xs font-mono text-slate-400 select-none">python</span><button aria-label="Copy code" class="absolute top-2 right-2 hidden group-hover/code:flex items-center gap-1 px-2 py-1 rounded text-xs font-medium bg-slate-700 text-slate-300 hover:bg-slate-600 transition-colors"><svg class="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M15.666 3.888A2.25 2.25 0 0013.5 2.25h-3c-1.03 0-1.9.693-2.166 1.638m7.332 0c.055.194.084.4.084.612v0a.75.75 0 01-.75.75H9a.75.75 0 01-.75-.75v0c0-.212.03-.418.084-.612m7.332 0c.646.049 1.288.11 1.927.184 1.1.128 1.907 1.077 1.907 2.185V19.5a2.25 2.25 0 01-2.25 2.25H6.75A2.25 2.25 0 014.5 19.5V6.257c0-1.108.806-2.057 1.907-2.185a48.208 48.208 0 011.927-.184"></path></svg>Copy</button><pre class="bg-slate-900 text-slate-100 rounded-lg overflow-x-auto text-sm font-mono pt-8 pb-4 px-4"><code># mymodule/controllers/main.py from odoo.addons.website.controllers.main import Website class WebsiteCustom(Website): def _get_lang_alternates(self, **kwargs): # Return list of {lang: 'en', url: '/en/page'} dicts ...</code></pre></div><p class="text-slate-600 leading-relaxed my-4 text-sm">And in the template:</p><div class="relative group/code my-6"><span class="absolute top-2 left-4 text-xs font-mono text-slate-400 select-none">xml</span><button aria-label="Copy code" class="absolute top-2 right-2 hidden group-hover/code:flex items-center gap-1 px-2 py-1 rounded text-xs font-medium bg-slate-700 text-slate-300 hover:bg-slate-600 transition-colors"><svg class="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M15.666 3.888A2.25 2.25 0 0013.5 2.25h-3c-1.03 0-1.9.693-2.166 1.638m7.332 0c.055.194.084.4.084.612v0a.75.75 0 01-.75.75H9a.75.75 0 01-.75-.75v0c0-.212.03-.418.084-.612m7.332 0c.646.049 1.288.11 1.927.184 1.1.128 1.907 1.077 1.907 2.185V19.5a2.25 2.25 0 01-2.25 2.25H6.75A2.25 2.25 0 014.5 19.5V6.257c0-1.108.806-2.057 1.907-2.185a48.208 48.208 0 011.927-.184"></path></svg>Copy</button><pre class="bg-slate-900 text-slate-100 rounded-lg overflow-x-auto text-sm font-mono pt-8 pb-4 px-4"><code><t t-foreach="lang_alternates" t-as="alt"> <link rel="alternate" t-att-hreflang="alt['lang']" t-att-href="alt['url']"/> </t></code></pre></div><h2 id="core-web-vitals-and-page-speed" class="group text-xl font-bold text-slate-900 mt-10 mb-4 scroll-mt-20"><a href="#core-web-vitals-and-page-speed" class="no-underline">Core Web Vitals and page speed<span class="ml-2 opacity-0 group-hover:opacity-100 transition-opacity text-slate-400 font-normal text-sm">#</span></a></h2><p class="text-slate-600 leading-relaxed my-4 text-sm">Odoo website pages load Bootstrap, jQuery, owl.js, and the Odoo web client on every page. The default payload is heavy for a marketing site.</p><p class="text-slate-600 leading-relaxed my-4 text-sm"><strong>Practical optimizations:</strong></p><ol class="list-decimal list-inside space-y-2 text-slate-600 my-4 text-sm leading-relaxed"><li><strong>Disable unused modules.</strong> Each installed module may add assets to <code class="bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono">web.assets_frontend</code>. Uninstall modules not used on the website (HR, Project, etc.).</li></ol><ol class="list-decimal list-inside space-y-2 text-slate-600 my-4 text-sm leading-relaxed"><li><strong>Use a CDN.</strong> Website → Configuration → Settings → Website → CDN. Set a CDN URL for static assets. Odoo appends a version query string (<code class="bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono">?t=12345</code>) to bust caches.</li></ol><ol class="list-decimal list-inside space-y-2 text-slate-600 my-4 text-sm leading-relaxed"><li><strong>Image optimization.</strong> Odoo resizes uploaded images and serves them in WebP where supported. Use the image widget's "Quality" option to reduce file size. Prefer responsive images via <code class="bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono">t-att-src</code> with the Odoo image route (<code class="bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono">/web/image/product.template/1/image_1920</code>).</li></ol><ol class="list-decimal list-inside space-y-2 text-slate-600 my-4 text-sm leading-relaxed"><li><strong>Lazy loading.</strong> Add <code class="bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono">loading="lazy"</code> to images below the fold. Odoo website editor does not add this automatically.</li></ol><ol class="list-decimal list-inside space-y-2 text-slate-600 my-4 text-sm leading-relaxed"><li><strong>Defer non-critical JS.</strong> Custom scripts added to <code class="bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono">web.assets_frontend</code> load synchronously. Move non-critical scripts to a deferred bundle or add <code class="bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono">defer</code> attribute via the asset template.</li></ol><h2 id="testing" class="group text-xl font-bold text-slate-900 mt-10 mb-4 scroll-mt-20"><a href="#testing" class="no-underline">Testing<span class="ml-2 opacity-0 group-hover:opacity-100 transition-opacity text-slate-400 font-normal text-sm">#</span></a></h2><p class="text-slate-600 leading-relaxed my-4 text-sm">After deploying SEO changes:</p><ol class="list-decimal list-inside space-y-2 text-slate-600 my-4 text-sm leading-relaxed"><li>Google Search Console → URL Inspection → verify meta tags.</li><li>Google Rich Results Test → verify structured data.</li><li>PageSpeed Insights (pagespeed.web.dev) → measure Core Web Vitals.</li><li>Screaming Frog or Ahrefs → crawl the sitemap, check for broken canonical tags, duplicate meta descriptions.</li></ol><p class="text-slate-600 leading-relaxed my-4 text-sm">The most impactful single change for most Odoo websites is image size reduction. Odoo's drag-and-drop editor makes it easy to upload 4 MB PNGs that appear as 300 px thumbnails.</p></article><div class="mt-10 flex items-center gap-3"><span class="text-xs text-slate-400">Share</span><a href="https://twitter.com/intent/tweet?text=Odoo%20website%20SEO%3A%20meta%20tags%2C%20JSON-LD%20structured%20data%2C%20sitemap%2C%20and%20page%20speed&url=https%3A%2F%2Ferpeek.ai%2Fblog%2Fodoo-website-seo-structured-data-sitemap" target="_blank" rel="noopener noreferrer" class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded text-xs font-medium text-slate-600 bg-slate-100 hover:bg-slate-200 transition-colors"><svg class="w-3.5 h-3.5" viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.74l7.73-8.835L1.254 2.25H8.08l4.253 5.622zm-1.161 17.52h1.833L7.084 4.126H5.117z"></path></svg>X</a><a href="https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Ferpeek.ai%2Fblog%2Fodoo-website-seo-structured-data-sitemap" target="_blank" rel="noopener noreferrer" class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded text-xs font-medium text-slate-600 bg-slate-100 hover:bg-slate-200 transition-colors"><svg class="w-3.5 h-3.5" viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 0 1-2.063-2.065 2.064 2.064 0 1 1 2.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"></path></svg>LinkedIn</a></div><div class="mt-10 pt-8 border-t border-slate-200"><p class="text-sm text-slate-500 mb-4">Try ERPeek on your own Odoo module - ask questions, scaffold tests, and explore your codebase in plain language.</p><a class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-primary-600 hover:bg-primary-700 rounded-lg transition-colors" href="/register">Get started free<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3"></path></svg></a></div><nav aria-label="Post navigation" class="flex items-stretch gap-4 mt-12 pt-8 border-t border-slate-200"><a class="flex-1 group flex flex-col gap-1 p-4 rounded-lg border border-slate-200 hover:border-primary-300 hover:bg-primary-50 transition-colors" href="/blog/odoo-server-actions-automated-business-logic"><span class="inline-flex items-center gap-1 text-xs text-slate-400 group-hover:text-primary-500 transition-colors"><svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18"></path></svg>Previous</span><span class="text-xs font-semibold text-slate-700 group-hover:text-primary-700 leading-snug line-clamp-2 transition-colors">Odoo server actions: when to use them instead of computed fields or OWL components</span></a><a class="flex-1 group flex flex-col gap-1 p-4 rounded-lg border border-slate-200 hover:border-primary-300 hover:bg-primary-50 transition-colors text-right" href="/blog/odoo-reconciliation-bank-matching-rules"><span class="inline-flex items-center justify-end gap-1 text-xs text-slate-400 group-hover:text-primary-500 transition-colors">Next<svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3"></path></svg></span><span class="text-xs font-semibold text-slate-700 group-hover:text-primary-700 leading-snug line-clamp-2 transition-colors">Odoo bank reconciliation: matching rules, statement import, and reconciliation models</span></a></nav><div class="mt-16 pt-10 border-t border-slate-200"><h2 class="text-base font-semibold text-slate-900 mb-6">Related articles</h2><div class="space-y-6"><article class="group"><a class="block" href="/blog/odoo-pricing-explained"><div class="flex items-center flex-wrap gap-2 mb-1"><span class="inline-block px-1.5 py-0.5 rounded text-xs font-medium bg-slate-100 text-slate-600">General</span><span class="text-slate-300" aria-hidden="true">·</span><time class="text-xs font-medium text-slate-400">August 24, 2026</time><span class="text-slate-300" aria-hidden="true">·</span><span class="text-xs text-slate-400">9<!-- --> min</span></div><h3 class="text-sm font-semibold text-slate-900 group-hover:text-primary-600 transition-colors mb-1.5 leading-snug">Odoo Pricing Explained: Users, Apps, and What Your Bill Actually Covers</h3><p class="text-xs text-slate-500 leading-relaxed line-clamp-2">A plain-language breakdown of how Odoo's pricing model works - per-user fees, app bundles, hosting choices, partner markup, and the line items that surprise first-time buyers.</p><span class="inline-flex items-center gap-1 mt-2 text-xs font-medium text-primary-600 group-hover:text-primary-700 transition-colors">Read article<svg class="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3"></path></svg></span></a></article><article class="group"><a class="block" href="/blog/odoo-vendor-bill-digitization-ocr"><div class="flex items-center flex-wrap gap-2 mb-1"><span class="inline-block px-1.5 py-0.5 rounded text-xs font-medium bg-slate-100 text-slate-600">General</span><span class="text-slate-300" aria-hidden="true">·</span><time class="text-xs font-medium text-slate-400">August 10, 2026</time><span class="text-slate-300" aria-hidden="true">·</span><span class="text-xs text-slate-400">9<!-- --> min</span></div><h3 class="text-sm font-semibold text-slate-900 group-hover:text-primary-600 transition-colors mb-1.5 leading-snug">Odoo vendor bill digitization: AI-powered OCR, the accounting inbox, and automated coding</h3><p class="text-xs text-slate-500 leading-relaxed line-clamp-2">Odoo's digitization feature reads vendor bill PDFs and images with an OCR pipeline, extracts vendor, date, amount, and line items, then proposes a draft bill ready for validation. Here is how the feature works, what it requires, and how to configure it for reliable processing.</p><span class="inline-flex items-center gap-1 mt-2 text-xs font-medium text-primary-600 group-hover:text-primary-700 transition-colors">Read article<svg class="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3"></path></svg></span></a></article></div></div></div></div></section></main><footer class="dark-section"><div class="mx-auto w-full max-w-[1280px] px-6 sm:px-8 lg:px-12"><div class="pt-16 pb-8" style="transition-property:opacity, transform, filter;transition-timing-function:cubic-bezier(0.22, 1, 0.36, 1);transition-duration:700ms;transition-delay:0ms;opacity:1"><div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-12 lg:gap-8"><div class="lg:col-span-2"><a class="inline-block" href="/"><img alt="ERPeek" width="300" height="96" decoding="async" data-nimg="1" class="h-16 w-auto object-contain" style="color:transparent" srcSet="/_next/image?url=%2Flogo-white.png&w=384&q=75 1x, /_next/image?url=%2Flogo-white.png&w=640&q=75 2x" src="/_next/image?url=%2Flogo-white.png&w=640&q=75"/></a><p class="mt-4 text-sm text-slate-400 max-w-xs leading-relaxed">AI-powered intelligence for your Odoo environment. Get precise, verified answers about your configuration and processes.</p></div><div><h3 class="text-sm font-semibold text-white mb-4">Product</h3><ul class="space-y-3"><li><a class="text-sm text-slate-400 hover:text-white transition-colors duration-200" href="/#features">Features</a></li><li><a class="text-sm text-slate-400 hover:text-white transition-colors duration-200" href="/pricing">Pricing</a></li><li><a class="text-sm text-slate-400 hover:text-white transition-colors duration-200" href="/changelog">Changelog</a></li><li><a class="text-sm text-slate-400 hover:text-white transition-colors duration-200" href="/docs">Documentation</a></li><li><a class="text-sm text-slate-400 hover:text-white transition-colors duration-200" href="/connect-mcp">MCP connector</a></li><li><a class="text-sm text-slate-400 hover:text-white transition-colors duration-200" href="/docs/faq">FAQ</a></li></ul></div><div><h3 class="text-sm font-semibold text-white mb-4">Company</h3><ul class="space-y-3"><li><a class="text-sm text-slate-400 hover:text-white transition-colors duration-200" href="/blog">Blog</a></li><li><a class="text-sm text-slate-400 hover:text-white transition-colors duration-200" href="/partners">Partners</a></li><li><a class="text-sm text-slate-400 hover:text-white transition-colors duration-200" href="/book-a-call">Book a Call</a></li><li><a class="text-sm text-slate-400 hover:text-white transition-colors duration-200" href="/contact">Contact</a></li></ul></div><div><h3 class="text-sm font-semibold text-white mb-4">Trust & legal</h3><ul class="space-y-3"><li><a class="text-sm text-slate-400 hover:text-white transition-colors duration-200" href="/security/one-pager">Security</a></li><li><a class="text-sm text-slate-400 hover:text-white transition-colors duration-200" href="/data-handling">Data handling</a></li><li><a class="text-sm text-slate-400 hover:text-white transition-colors duration-200" href="/terms">Terms & Conditions</a></li><li><a class="text-sm text-slate-400 hover:text-white transition-colors duration-200" href="/privacy">Privacy Policy</a></li><li><a class="text-sm text-slate-400 hover:text-white transition-colors duration-200" href="/cookies">Cookie Policy</a></li></ul></div></div><div class="mt-12 pt-8 border-t border-slate-800 flex flex-col sm:flex-row items-center justify-between gap-4"><p class="text-sm text-slate-500">© <!-- -->2026<!-- --> ERPeek. All rights reserved.</p></div></div></div></footer><!--$--><!--/$--><script src="/_next/static/chunks/2pqa1hri5aikf.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[524994,[\"/_next/static/chunks/2gavq8i20rckw.js\",\"/_next/static/chunks/1hnnpgs2j-ldd.js\",\"/_next/static/chunks/1sjiknkyekxu6.js\",\"/_next/static/chunks/1dzhmhzdo1uo1.js\",\"/_next/static/chunks/0ldixr8dnci3i.js\"],\"AuthProvider\"]\n3:I[339756,[\"/_next/static/chunks/2gavq8i20rckw.js\",\"/_next/static/chunks/1hnnpgs2j-ldd.js\",\"/_next/static/chunks/1sjiknkyekxu6.js\",\"/_next/static/chunks/1dzhmhzdo1uo1.js\",\"/_next/static/chunks/0ldixr8dnci3i.js\"],\"default\"]\n4:I[408821,[\"/_next/static/chunks/2gavq8i20rckw.js\",\"/_next/static/chunks/1hnnpgs2j-ldd.js\",\"/_next/static/chunks/1sjiknkyekxu6.js\",\"/_next/static/chunks/1dzhmhzdo1uo1.js\",\"/_next/static/chunks/0ldixr8dnci3i.js\",\"/_next/static/chunks/2ebyxv3kx063p.js\"],\"default\"]\n5:I[837457,[\"/_next/static/chunks/2gavq8i20rckw.js\",\"/_next/static/chunks/1hnnpgs2j-ldd.js\",\"/_next/static/chunks/1sjiknkyekxu6.js\",\"/_next/static/chunks/1dzhmhzdo1uo1.js\",\"/_next/static/chunks/0ldixr8dnci3i.js\"],\"default\"]\n6:I[725982,[\"/_next/static/chunks/2gavq8i20rckw.js\",\"/_next/static/chunks/1hnnpgs2j-ldd.js\",\"/_next/static/chunks/1sjiknkyekxu6.js\",\"/_next/static/chunks/1dzhmhzdo1uo1.js\",\"/_next/static/chunks/0ldixr8dnci3i.js\",\"/_next/static/chunks/0y_lckteoprnn.js\"],\"SiteHeader\"]\n7:I[883079,[\"/_next/static/chunks/2gavq8i20rckw.js\",\"/_next/static/chunks/1hnnpgs2j-ldd.js\",\"/_next/static/chunks/1sjiknkyekxu6.js\",\"/_next/static/chunks/1dzhmhzdo1uo1.js\",\"/_next/static/chunks/0ldixr8dnci3i.js\",\"/_next/static/chunks/2mbik3e-evhp5.js\"],\"Button\"]\n8:I[201316,[\"/_next/static/chunks/2gavq8i20rckw.js\",\"/_next/static/chunks/1hnnpgs2j-ldd.js\",\"/_next/static/chunks/1sjiknkyekxu6.js\",\"/_next/static/chunks/1dzhmhzdo1uo1.js\",\"/_next/static/chunks/0ldixr8dnci3i.js\",\"/_next/static/chunks/0y_lckteoprnn.js\"],\"SiteFooter\"]\n9:I[810515,[\"/_next/static/chunks/2gavq8i20rckw.js\",\"/_next/static/chunks/1hnnpgs2j-ldd.js\",\"/_next/static/chunks/1sjiknkyekxu6.js\",\"/_next/static/chunks/1dzhmhzdo1uo1.js\",\"/_next/static/chunks/0ldixr8dnci3i.js\"],\"FeedbackLauncher\"]\na:I[645942,[\"/_next/static/chunks/2gavq8i20rckw.js\",\"/_next/static/chunks/1hnnpgs2j-ldd.js\",\"/_next/static/chunks/1sjiknkyekxu6.js\",\"/_next/static/chunks/1dzhmhzdo1uo1.js\",\"/_next/static/chunks/0ldixr8dnci3i.js\"],\"CookieNotice\"]\nb:I[322663,[\"/_next/static/chunks/2gavq8i20rckw.js\",\"/_next/static/chunks/1hnnpgs2j-ldd.js\",\"/_next/static/chunks/1sjiknkyekxu6.js\",\"/_next/static/chunks/1dzhmhzdo1uo1.js\",\"/_next/static/chunks/0ldixr8dnci3i.js\"],\"GoogleAnalytics\"]\nd:I[897367,[\"/_next/static/chunks/2gavq8i20rckw.js\",\"/_next/static/chunks/1hnnpgs2j-ldd.js\",\"/_next/static/chunks/1sjiknkyekxu6.js\",\"/_next/static/chunks/1dzhmhzdo1uo1.js\",\"/_next/static/chunks/0ldixr8dnci3i.js\"],\"OutletBoundary\"]\ne:\"$Sreact.suspense\"\n11:I[897367,[\"/_next/static/chunks/2gavq8i20rckw.js\",\"/_next/static/chunks/1hnnpgs2j-ldd.js\",\"/_next/static/chunks/1sjiknkyekxu6.js\",\"/_next/static/chunks/1dzhmhzdo1uo1.js\",\"/_next/static/chunks/0ldixr8dnci3i.js\"],\"ViewportBoundary\"]\n13:I[897367,[\"/_next/static/chunks/2gavq8i20rckw.js\",\"/_next/static/chunks/1hnnpgs2j-ldd.js\",\"/_next/static/chunks/1sjiknkyekxu6.js\",\"/_next/static/chunks/1dzhmhzdo1uo1.js\",\"/_next/static/chunks/0ldixr8dnci3i.js\"],\"MetadataBoundary\"]\n15:I[168027,[\"/_next/static/chunks/2gavq8i20rckw.js\",\"/_next/static/chunks/1hnnpgs2j-ldd.js\",\"/_next/static/chunks/1sjiknkyekxu6.js\",\"/_next/static/chunks/1dzhmhzdo1uo1.js\",\"/_next/static/chunks/0ldixr8dnci3i.js\"],\"default\",1]\n19:I[522016,[\"/_next/static/chunks/2gavq8i20rckw.js\",\"/_next/static/chunks/1hnnpgs2j-ldd.js\",\"/_next/static/chunks/1sjiknkyekxu6.js\",\"/_next/static/chunks/1dzhmhzdo1uo1.js\",\"/_next/static/chunks/0ldixr8dnci3i.js\",\"/_next/static/chunks/0y_lckteoprnn.js\"],\"\"]\n48:I[787229,[\"/_next/static/chunks/2gavq8i20rckw.js\",\"/_next/static/chunks/1hnnpgs2j-ldd.js\",\"/_next/static/chunks/1sjiknkyekxu6.js\",\"/_next/static/chunks/1dzhmhzdo1uo1.js\",\"/_next/static/chunks/0ldixr8dnci3i.js\",\"/_next/static/chunks/0y_lckteoprnn.js\"],\"CopyCodeBlock\"]\n49:I[27201,[\"/_next/static/chunks/2gavq8i20rckw.js\",\"/_next/static/chunks/1hnnpgs2j-ldd.js\",\"/_next/static/chunks/1sjiknkyekxu6.js\",\"/_next/static/chunks/1dzhmhzdo1uo1"])</script><script>self.__next_f.push([1,".js\",\"/_next/static/chunks/0ldixr8dnci3i.js\"],\"IconMark\"]\n:HL[\"/_next/static/chunks/0yp73l8t7jy8y.css\",\"style\"]\n:HL[\"/_next/static/chunks/2dada7oxncbf7.css\",\"style\"]\n:HL[\"/_next/static/media/caveat_latin_400_normal-s.p.3r_2tlsk65eum.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/caveat_latin_500_normal-s.p.2oynjr4i06dor.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/caveat_latin_600_normal-s.p.2cwz_0qwo_1oi.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/caveat_latin_700_normal-s.p.05jlb5hscku72.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/inter_latin_400_normal-s.p.2qdljeg3s-lsl.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/inter_latin_500_normal-s.p.1d14jwmkqqa0f.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/inter_latin_600_normal-s.p.2dov6rjg62vru.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/inter_latin_700_normal-s.p.4421omqeymgmp.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/jetbrains_mono_latin_400_normal-s.p.3crsbyy6lh6yf.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/jetbrains_mono_latin_500_normal-s.p.2h52d08o60qht.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/jetbrains_mono_latin_700_normal-s.p.1ydlpv6k6mttm.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/patrick_hand_latin_400_normal-s.p.3x8ls3bzy2y5u.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/playfair_display_latin_400_normal-s.p.2zfucbp6idj7x.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/playfair_display_latin_500_normal-s.p.1to3h1yjpwzkk.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/playfair_display_latin_600_normal-s.p.2hfg4ls1gllkc.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/playfair_display_latin_700_normal-s.p.0nie7e_p69_i8.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/playfair_display_latin_800_normal-s.p.2m7lwaj-jk3v5.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"c\":[\"\",\"blog\",\"odoo-website-seo-structured-data-sitemap\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"blog\",{\"children\":[[\"slug\",\"odoo-website-seo-structured-data-sitemap\",\"d\",null],{\"children\":[\"__PAGE__\",{}]}]}]},\"$undefined\",\"$undefined\",16],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0yp73l8t7jy8y.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"link\",\"1\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/2dada7oxncbf7.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/2gavq8i20rckw.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/1hnnpgs2j-ldd.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-2\",{\"src\":\"/_next/static/chunks/1sjiknkyekxu6.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-3\",{\"src\":\"/_next/static/chunks/1dzhmhzdo1uo1.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-4\",{\"src\":\"/_next/static/chunks/0ldixr8dnci3i.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"data-scroll-behavior\":\"smooth\",\"children\":[\"$\",\"body\",null,{\"className\":\"inter_f351078b-module__zWQQlW__variable playfair_e82ebcb8-module__Y9PJiG__variable jetbrainsmono_5913b8af-module__SlyEFq__variable caveat_994cfc15-module__Hs8uKq__variable patrickhand_e4bb85d9-module__Fh3pnG__variable font-sans antialiased bg-slate-50 text-slate-900\",\"suppressHydrationWarning\":true,\"children\":[[\"$\",\"script\",null,{\"type\":\"application/ld+json\",\"dangerouslySetInnerHTML\":{\"__html\":\"{\\\"@context\\\":\\\"https://schema.org\\\",\\\"@graph\\\":[{\\\"@type\\\":\\\"Organization\\\",\\\"@id\\\":\\\"https://erpeek.ai/#organization\\\",\\\"name\\\":\\\"ERPeek\\\",\\\"url\\\":\\\"https://erpeek.ai\\\",\\\"logo\\\":{\\\"@type\\\":\\\"ImageObject\\\",\\\"url\\\":\\\"https://erpeek.ai/logo.png\\\",\\\"width\\\":512,\\\"height\\\":512},\\\"description\\\":\\\"AI-powered code intelligence platform for Odoo ERP. Get precise, version-scoped answers grounded in actual source code.\\\",\\\"contactPoint\\\":{\\\"@type\\\":\\\"ContactPoint\\\",\\\"contactType\\\":\\\"customer support\\\",\\\"email\\\":\\\"support@erpeek.ai\\\",\\\"url\\\":\\\"https://erpeek.ai/contact\\\"}},{\\\"@type\\\":\\\"WebSite\\\",\\\"@id\\\":\\\"https://erpeek.ai/#website\\\",\\\"name\\\":\\\"ERPeek\\\",\\\"url\\\":\\\"https://erpeek.ai\\\",\\\"publisher\\\":{\\\"@id\\\":\\\"https://erpeek.ai/#organization\\\"}}]}\"}}],[\"$\",\"$L2\",null,{\"children\":[[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$4\",\"errorStyles\":[],\"errorScripts\":[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/2ebyxv3kx063p.js\",\"async\":true}]],\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"$L6\",null,{}],[\"$\",\"main\",null,{\"children\":[\"$\",\"div\",null,{\"className\":\"mx-auto w-full max-w-[1280px] px-6 sm:px-8 lg:px-12\",\"children\":[\"$\",\"div\",null,{\"className\":\"flex flex-col items-center justify-center py-32 text-center\",\"children\":[[\"$\",\"div\",null,{\"className\":\"text-8xl font-bold text-slate-200 font-display mb-4\",\"children\":\"404\"}],[\"$\",\"h1\",null,{\"className\":\"text-2xl font-bold text-slate-900 mb-2\",\"children\":\"Page not found\"}],[\"$\",\"p\",null,{\"className\":\"text-slate-500 mb-8 max-w-md\",\"children\":\"The page you're looking for doesn't exist or has been moved. Let's get you back on track.\"}],[\"$\",\"div\",null,{\"className\":\"flex gap-4\",\"children\":[[\"$\",\"$L7\",null,{\"as\":\"a\",\"href\":\"/\",\"children\":\"Go Home\"}],[\"$\",\"$L7\",null,{\"as\":\"a\",\"href\":\"/docs\",\"variant\":\"outline\",\"children\":\"View Docs\"}]]}]]}]}]}],[\"$\",\"$L8\",null,{}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}],[\"$\",\"$L9\",null,{}]]}],[\"$\",\"$La\",null,{}],[\"$\",\"$Lb\",null,{}]]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[\"$Lc\",[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/0y_lckteoprnn.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$Ld\",null,{\"children\":[\"$\",\"$e\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@f\"}]}]]}],{},null,false,null]},null,false,\"$@10\"]},null,false,\"$@10\"]},null,false,null],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$L11\",null,{\"children\":\"$L12\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$L13\",null,{\"children\":[\"$\",\"$e\",null,{\"name\":\"Next.Metadata\",\"children\":\"$L14\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$15\",[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0yp73l8t7jy8y.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],\"$L16\"]],\"S\":false,\"h\":null,\"s\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"kw_lsq_19nXmDkuskmYYR\"}\n"])</script><script>self.__next_f.push([1,"17:[]\n10:\"$W17\"\n16:[\"$\",\"link\",\"1\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/2dada7oxncbf7.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]\n18:T422,{\"@context\":\"https://schema.org\",\"@type\":\"BlogPosting\",\"headline\":\"Odoo website SEO: meta tags, JSON-LD structured data, sitemap, and page speed\",\"description\":\"Odoo Website includes SEO tools for meta titles, descriptions, and XML sitemaps, but most structured data and Core Web Vitals optimization requires custom QWeb template overrides. Here is what works out of the box and what you must build.\",\"datePublished\":\"2026-08-17\",\"url\":\"https://erpeek.ai/blog/odoo-website-seo-structured-data-sitemap\",\"inLanguage\":\"en\",\"wordCount\":707,\"image\":{\"@type\":\"ImageObject\",\"url\":\"https://erpeek.ai/og-image.png\",\"width\":1200,\"height\":630},\"author\":{\"@type\":\"Organization\",\"name\":\"ERPeek\",\"url\":\"https://erpeek.ai\"},\"publisher\":{\"@type\":\"Organization\",\"name\":\"ERPeek\",\"url\":\"https://erpeek.ai\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://erpeek.ai/logo.png\"}},\"mainEntityOfPage\":{\"@type\":\"WebPage\",\"@id\":\"https://erpeek.ai/blog/odoo-website-seo-structured-data-sitemap\"},\"keywords\":\"odoo website seo, Odoo, ERPeek\",\"timeRequired\":\"PT7M\",\"articleSection\":\"General\"}"])</script><script>self.__next_f.push([1,"c:[[\"$\",\"script\",null,{\"type\":\"application/ld+json\",\"dangerouslySetInnerHTML\":{\"__html\":\"$18\"}}],[\"$\",\"script\",null,{\"type\":\"application/ld+json\",\"dangerouslySetInnerHTML\":{\"__html\":\"{\\\"@context\\\":\\\"https://schema.org\\\",\\\"@type\\\":\\\"BreadcrumbList\\\",\\\"itemListElement\\\":[{\\\"@type\\\":\\\"ListItem\\\",\\\"position\\\":1,\\\"name\\\":\\\"Home\\\",\\\"item\\\":\\\"https://erpeek.ai\\\"},{\\\"@type\\\":\\\"ListItem\\\",\\\"position\\\":2,\\\"name\\\":\\\"Blog\\\",\\\"item\\\":\\\"https://erpeek.ai/blog\\\"},{\\\"@type\\\":\\\"ListItem\\\",\\\"position\\\":3,\\\"name\\\":\\\"Odoo website SEO: meta tags, JSON-LD structured data, sitemap, and page speed\\\",\\\"item\\\":\\\"https://erpeek.ai/blog/odoo-website-seo-structured-data-sitemap\\\"}]}\"}}],[\"$\",\"$L6\",null,{}],[\"$\",\"main\",null,{\"children\":[\"$\",\"section\",null,{\"id\":\"$undefined\",\"className\":\"py-20 md:py-24 bg-slate-50\",\"children\":[\"$\",\"div\",null,{\"className\":\"mx-auto w-full max-w-[1280px] px-6 sm:px-8 lg:px-12\",\"children\":[\"$\",\"div\",null,{\"className\":\"max-w-2xl mx-auto\",\"children\":[[\"$\",\"$L19\",null,{\"href\":\"/blog\",\"className\":\"inline-flex items-center gap-1.5 text-xs font-medium text-slate-500 hover:text-slate-900 transition-colors mb-8\",\"children\":[[\"$\",\"svg\",null,{\"className\":\"w-3.5 h-3.5\",\"fill\":\"none\",\"viewBox\":\"0 0 24 24\",\"strokeWidth\":2,\"stroke\":\"currentColor\",\"children\":[\"$\",\"path\",null,{\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"d\":\"M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18\"}]}],\"All posts\"]}],[\"$\",\"header\",null,{\"className\":\"mb-10\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex items-center flex-wrap gap-2 mb-3\",\"children\":[[\"$\",\"span\",null,{\"className\":\"inline-block px-2 py-0.5 rounded text-xs font-medium bg-slate-100 text-slate-600\",\"children\":\"General\"}],[\"$\",\"span\",null,{\"className\":\"text-slate-300\",\"aria-hidden\":\"true\",\"children\":\"·\"}],[\"$\",\"time\",null,{\"className\":\"text-xs font-medium text-slate-400\",\"children\":\"August 17, 2026\"}],[\"$\",\"span\",null,{\"className\":\"text-slate-300\",\"aria-hidden\":\"true\",\"children\":\"·\"}],[\"$\",\"span\",null,{\"className\":\"text-xs font-medium text-slate-400\",\"children\":[7,\" min read\"]}]]}],[\"$\",\"h1\",null,{\"className\":\"text-2xl font-bold text-slate-900 leading-snug mb-4\",\"children\":\"Odoo website SEO: meta tags, JSON-LD structured data, sitemap, and page speed\"}],[\"$\",\"p\",null,{\"className\":\"text-sm text-slate-500 leading-relaxed\",\"children\":\"Odoo Website includes SEO tools for meta titles, descriptions, and XML sitemaps, but most structured data and Core Web Vitals optimization requires custom QWeb template overrides. Here is what works out of the box and what you must build.\"}],[\"$\",\"div\",null,{\"className\":\"mt-6 pt-6 border-t border-slate-200\"}]]}],null,[\"$\",\"article\",null,{\"className\":\"prose-custom\",\"children\":[[\"$\",\"p\",\"2\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"Odoo's website module includes basic SEO controls, but \\\"basic\\\" is accurate: per-page meta title and description editing, a generated sitemap, and an Open Graph image. Structured data (JSON-LD), canonical URLs, hreflang tags, and Core Web Vitals optimization all require custom work. Here is a realistic picture of what Odoo handles automatically versus what you build.\"}}],\"$L1a\",\"$L1b\",\"$L1c\",\"$L1d\",\"$L1e\",\"$L1f\",\"$L20\",\"$L21\",\"$L22\",\"$L23\",\"$L24\",\"$L25\",\"$L26\",\"$L27\",\"$L28\",\"$L29\",\"$L2a\",\"$L2b\",\"$L2c\",\"$L2d\",\"$L2e\",\"$L2f\",\"$L30\",\"$L31\",\"$L32\",\"$L33\",\"$L34\",\"$L35\",\"$L36\",\"$L37\",\"$L38\",\"$L39\",\"$L3a\",\"$L3b\",\"$L3c\",\"$L3d\",\"$L3e\",\"$L3f\",\"$L40\",\"$L41\",\"$L42\"]}],\"$L43\",\"$L44\",\"$L45\",\"$L46\"]}]}]}]}],\"$L47\"]\n"])</script><script>self.__next_f.push([1,"1a:[\"$\",\"h2\",\"4\",{\"id\":\"what-odoo-website-includes-by-default\",\"className\":\"group text-xl font-bold text-slate-900 mt-10 mb-4 scroll-mt-20\",\"children\":[\"$\",\"a\",null,{\"href\":\"#what-odoo-website-includes-by-default\",\"className\":\"no-underline\",\"dangerouslySetInnerHTML\":{\"__html\":\"What Odoo Website includes by default\u003cspan class=\\\"ml-2 opacity-0 group-hover:opacity-100 transition-opacity text-slate-400 font-normal text-sm\\\"\u003e#\u003c/span\u003e\"}}]}]\n1b:[\"$\",\"p\",\"6\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003ePer-page SEO editor:\u003c/strong\u003e\"}}]\n1c:[\"$\",\"p\",\"7\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"Each website page, blog post, product page, and event page has an SEO panel (visible in the website editor: Promote → Search Engine Optimization). Fields:\"}}]\n1d:[\"$\",\"ul\",\"11\",{\"className\":\"list-disc list-inside space-y-2 text-slate-600 my-4 text-sm leading-relaxed\",\"children\":[[\"$\",\"li\",\"0\",{\"dangerouslySetInnerHTML\":{\"__html\":\"Title (populates \u003ccode class=\\\"bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono\\\"\u003e\u003ctitle\u003e\u003c/code\u003e and OG title)\"}}],[\"$\",\"li\",\"1\",{\"dangerouslySetInnerHTML\":{\"__html\":\"Description (populates \u003ccode class=\\\"bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono\\\"\u003e\u003cmeta name=\\\"description\\\"\u003e\u003c/code\u003e and OG description)\"}}],[\"$\",\"li\",\"2\",{\"dangerouslySetInnerHTML\":{\"__html\":\"Keywords (not used by modern search engines; can be ignored)\"}}]]}]\n1e:[\"$\",\"p\",\"12\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eXML sitemap:\u003c/strong\u003e\"}}]\n1f:[\"$\",\"p\",\"13\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"Automatically generated at \u003ccode class=\\\"bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono\\\"\u003e/sitemap.xml\u003c/code\u003e. Includes:\"}}]\n20:[\"$\",\"ul\",\"18\",{\"className\":\"list-disc list-inside space-y-2 text-slate-600 my-4 text-sm leading-relaxed\",\"children\":[[\"$\",\"li\",\"0\",{\"dangerouslySetInnerHTML\":{\"__html\":\"All published website pages.\"}}],[\"$\",\"li\",\"1\",{\"dangerouslySetInnerHTML\":{\"__html\":\"All published products (if eCommerce is enabled).\"}}],[\"$\",\"li\",\"2\",{\"dangerouslySetInnerHTML\":{\"__html\":\"All published blog posts.\"}}],[\"$\",\"li\",\"3\",{\"dangerouslySetInnerHTML\":{\"__html\":\"All events.\"}}]]}]\n21:[\"$\",\"p\",\"19\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"The sitemap updates when content publishes. Submit it to Google Search Console.\"}}]\n22:[\"$\",\"p\",\"21\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eRobots.txt:\u003c/strong\u003e\"}}]\n23:[\"$\",\"p\",\"22\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"Generated at \u003ccode class=\\\"bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono\\\"\u003e/robots.txt\u003c/code\u003e. Points to the sitemap. Configurable in Website → Configuration → Settings → SEO → Robots.txt.\"}}]\n24:[\"$\",\"p\",\"24\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eOpen Graph tags:\u003c/strong\u003e\"}}]\n25:[\"$\",\"p\",\"25\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"OG tags (\u003ccode class=\\\"bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono\\\"\u003eog:title\u003c/code\u003e, \u003ccode class=\\\"bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono\\\"\u003eog:description\u003c/code\u003e, \u003ccode class=\\\"bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono\\\"\u003eog:image\u003c/code\u003e) are populated from the SEO editor fields. OG image requires the page to have a cover image set.\"}}]\n26:[\"$\",\"h2\",\"27\",{\"id\":\"adding-json-ld-structured-data\",\"className\":\"group text-xl font-bold text-slate-900 mt-10 mb-4 scroll-mt-20\",\"children\":[\"$\",\"a\",null,{\"href\":\"#adding-json-ld-structured-data\",\"className\":\"no-underline\",\"dangerouslySetInnerHTML\":{\"__html\":\"Adding JSON-LD structured data\u003cspan class=\\\"ml-2 opacity-0 group-hover:opacity-100 transition-opacity "])</script><script>self.__next_f.push([1,"text-slate-400 font-normal text-sm\\\"\u003e#\u003c/span\u003e\"}}]}]\n27:[\"$\",\"p\",\"29\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"Odoo does not generate JSON-LD for products, blog posts, or events automatically. Add it via QWeb template inheritance.\"}}]\n28:[\"$\",\"p\",\"31\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eProduct schema (Product page):\u003c/strong\u003e\"}}]\n29:[\"$\",\"$L48\",\"53\",{\"code\":\"\u003ctemplate id=\\\"product_page_jsonld\\\" inherit_id=\\\"website_sale.product\\\"\u003e\\n \u003cxpath expr=\\\"//head\\\" position=\\\"inside\\\"\u003e\\n \u003cscript type=\\\"application/ld+json\\\"\u003e\\n {\\n \\\"@context\\\": \\\"https://schema.org\\\",\\n \\\"@type\\\": \\\"Product\\\",\\n \\\"name\\\": \\\"\u003ct t-esc=\\\"product.name\\\"/\u003e\\\",\\n \\\"description\\\": \\\"\u003ct t-esc=\\\"product.description_sale or ''\\\"/\u003e\\\",\\n \\\"sku\\\": \\\"\u003ct t-esc=\\\"product.default_code or ''\\\"/\u003e\\\",\\n \\\"offers\\\": {\\n \\\"@type\\\": \\\"Offer\\\",\\n \\\"priceCurrency\\\": \\\"\u003ct t-esc=\\\"website.currency_id.name\\\"/\u003e\\\",\\n \\\"price\\\": \\\"\u003ct t-esc=\\\"product.list_price\\\"/\u003e\\\",\\n \\\"availability\\\": \\\"https://schema.org/InStock\\\"\\n }\\n }\\n \u003c/script\u003e\\n \u003c/xpath\u003e\\n\u003c/template\u003e\",\"lang\":\"xml\"}]\n2a:[\"$\",\"p\",\"55\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eBlog post schema:\u003c/strong\u003e\"}}]\n2b:[\"$\",\"$L48\",\"74\",{\"code\":\"\u003ctemplate id=\\\"blog_post_jsonld\\\" inherit_id=\\\"website_blog.blog_post_complete\\\"\u003e\\n \u003cxpath expr=\\\"//head\\\" position=\\\"inside\\\"\u003e\\n \u003cscript type=\\\"application/ld+json\\\"\u003e\\n {\\n \\\"@context\\\": \\\"https://schema.org\\\",\\n \\\"@type\\\": \\\"BlogPosting\\\",\\n \\\"headline\\\": \\\"\u003ct t-esc=\\\"blog_post.name\\\"/\u003e\\\",\\n \\\"datePublished\\\": \\\"\u003ct t-esc=\\\"blog_post.post_date\\\"/\u003e\\\",\\n \\\"author\\\": {\\n \\\"@type\\\": \\\"Person\\\",\\n \\\"name\\\": \\\"\u003ct t-esc=\\\"blog_post.author_id.name\\\"/\u003e\\\"\\n }\\n }\\n \u003c/script\u003e\\n \u003c/xpath\u003e\\n\u003c/template\u003e\",\"lang\":\"xml\"}]\n2c:[\"$\",\"p\",\"76\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"Validate the output at Google's Rich Results Test.\"}}]\n2d:[\"$\",\"h2\",\"78\",{\"id\":\"canonical-urls\",\"className\":\"group text-xl font-bold text-slate-900 mt-10 mb-4 scroll-mt-20\",\"children\":[\"$\",\"a\",null,{\"href\":\"#canonical-urls\",\"className\":\"no-underline\",\"dangerouslySetInnerHTML\":{\"__html\":\"Canonical URLs\u003cspan class=\\\"ml-2 opacity-0 group-hover:opacity-100 transition-opacity text-slate-400 font-normal text-sm\\\"\u003e#\u003c/span\u003e\"}}]}]\n2e:[\"$\",\"p\",\"80\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"Odoo adds a \u003ccode class=\\\"bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono\\\"\u003e\u003clink rel=\\\"canonical\\\"\u003e\u003c/code\u003e tag to most pages pointing to the current URL. For product pages accessible via multiple URLs (e.g., category-filtered views), the canonical points to the product's base URL.\"}}]\n2f:[\"$\",\"p\",\"82\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"Override the canonical in edge cases:\"}}]\n30:[\"$\",\"$L48\",\"90\",{\"code\":\"\u003ctemplate id=\\\"custom_canonical\\\" inherit_id=\\\"website.layout\\\"\u003e\\n \u003cxpath expr=\\\"//link[@rel='canonical']\\\" position=\\\"replace\\\"\u003e\\n \u003clink rel=\\\"canonical\\\" t-attf-href=\\\"https://#{website.domain}/products/#{product.id}\\\"/\u003e\\n \u003c/xpath\u003e\\n\u003c/template\u003e\",\"lang\":\"xml\"}]\n31:[\"$\",\"h2\",\"92\",{\"id\":\"hreflang-for-multilingual-sites\",\"className\":\"group text-xl font-bold text-slate-900 mt-10 mb-4 scroll-mt-20\",\"children\":[\"$\",\"a\",null,{\"href\":\"#hreflang-for-multilingual-sites\",\"className\":\"no-underline\",\"dangerouslySetInnerHTML\":{\"__html\":\"hreflang for multilingual sites\u003cspan class=\\\"ml-2 opacity-0 group-hover:opacity-100 transition-opacity text-slate-400 font-normal text-sm\\\"\u003e#\u003c/span\u003e\"}}]}]\n32:[\"$\",\"p\",\"94\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"If you run Odoo website in multiple languages, search engines need \u003ccode class=\\\"bg-slate-100 text-slate-800 px-1 py-0.5 rou"])</script><script>self.__next_f.push([1,"nded text-xs font-mono\\\"\u003ehreflang\u003c/code\u003e tags to understand which language version to serve in which region. Odoo does not generate these automatically.\"}}]\n33:[\"$\",\"p\",\"96\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"Add them via a controller override:\"}}]\n34:[\"$\",\"$L48\",\"106\",{\"code\":\"# mymodule/controllers/main.py\\nfrom odoo.addons.website.controllers.main import Website\\n\\nclass WebsiteCustom(Website):\\n def _get_lang_alternates(self, **kwargs):\\n # Return list of {lang: 'en', url: '/en/page'} dicts\\n ...\",\"lang\":\"python\"}]\n35:[\"$\",\"p\",\"108\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"And in the template:\"}}]\n36:[\"$\",\"$L48\",\"114\",{\"code\":\"\u003ct t-foreach=\\\"lang_alternates\\\" t-as=\\\"alt\\\"\u003e\\n \u003clink rel=\\\"alternate\\\" t-att-hreflang=\\\"alt['lang']\\\" t-att-href=\\\"alt['url']\\\"/\u003e\\n\u003c/t\u003e\",\"lang\":\"xml\"}]\n37:[\"$\",\"h2\",\"116\",{\"id\":\"core-web-vitals-and-page-speed\",\"className\":\"group text-xl font-bold text-slate-900 mt-10 mb-4 scroll-mt-20\",\"children\":[\"$\",\"a\",null,{\"href\":\"#core-web-vitals-and-page-speed\",\"className\":\"no-underline\",\"dangerouslySetInnerHTML\":{\"__html\":\"Core Web Vitals and page speed\u003cspan class=\\\"ml-2 opacity-0 group-hover:opacity-100 transition-opacity text-slate-400 font-normal text-sm\\\"\u003e#\u003c/span\u003e\"}}]}]\n38:[\"$\",\"p\",\"118\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"Odoo website pages load Bootstrap, jQuery, owl.js, and the Odoo web client on every page. The default payload is heavy for a marketing site.\"}}]\n39:[\"$\",\"p\",\"120\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003ePractical optimizations:\u003c/strong\u003e\"}}]\n3a:[\"$\",\"ol\",\"123\",{\"className\":\"list-decimal list-inside space-y-2 text-slate-600 my-4 text-sm leading-relaxed\",\"children\":[[\"$\",\"li\",\"0\",{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eDisable unused modules.\u003c/strong\u003e Each installed module may add assets to \u003ccode class=\\\"bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono\\\"\u003eweb.assets_frontend\u003c/code\u003e. Uninstall modules not used on the website (HR, Project, etc.).\"}}]]}]\n3b:[\"$\",\"ol\",\"125\",{\"className\":\"list-decimal list-inside space-y-2 text-slate-600 my-4 text-sm leading-relaxed\",\"children\":[[\"$\",\"li\",\"0\",{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eUse a CDN.\u003c/strong\u003e Website → Configuration → Settings → Website → CDN. Set a CDN URL for static assets. Odoo appends a version query string (\u003ccode class=\\\"bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono\\\"\u003e?t=12345\u003c/code\u003e) to bust caches.\"}}]]}]\n3c:[\"$\",\"ol\",\"127\",{\"className\":\"list-decimal list-inside space-y-2 text-slate-600 my-4 text-sm leading-relaxed\",\"children\":[[\"$\",\"li\",\"0\",{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eImage optimization.\u003c/strong\u003e Odoo resizes uploaded images and serves them in WebP where supported. Use the image widget's \\\"Quality\\\" option to reduce file size. Prefer responsive images via \u003ccode class=\\\"bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono\\\"\u003et-att-src\u003c/code\u003e with the Odoo image route (\u003ccode class=\\\"bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono\\\"\u003e/web/image/product.template/1/image_1920\u003c/code\u003e).\"}}]]}]\n3d:[\"$\",\"ol\",\"129\",{\"className\":\"list-decimal list-inside space-y-2 text-slate-600 my-4 text-sm leading-relaxed\",\"children\":[[\"$\",\"li\",\"0\",{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eLazy loading.\u003c/strong\u003e Add \u003ccode class=\\\"bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono\\\"\u003eloading=\\\"lazy\\\"\u003c/code\u003e to images below the fold. Odoo website editor does not add this automatically.\"}}]]}]\n3e:[\"$\",\"ol\",\"131\",{\"className\":\"list-decimal list-inside space-y-2 text-slate-600 my-4 text-sm leading-relaxed\",\"children\":[[\"$\",\"li\",\"0\",{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eDefer non-critical JS.\u003c/strong\u003e Custom scripts added to \u003ccode class=\\\"bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono\\\"\u003eweb.assets_frontend\u003c/code\u003e load synchronously. Move non-critical sc"])</script><script>self.__next_f.push([1,"ripts to a deferred bundle or add \u003ccode class=\\\"bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono\\\"\u003edefer\u003c/code\u003e attribute via the asset template.\"}}]]}]\n3f:[\"$\",\"h2\",\"132\",{\"id\":\"testing\",\"className\":\"group text-xl font-bold text-slate-900 mt-10 mb-4 scroll-mt-20\",\"children\":[\"$\",\"a\",null,{\"href\":\"#testing\",\"className\":\"no-underline\",\"dangerouslySetInnerHTML\":{\"__html\":\"Testing\u003cspan class=\\\"ml-2 opacity-0 group-hover:opacity-100 transition-opacity text-slate-400 font-normal text-sm\\\"\u003e#\u003c/span\u003e\"}}]}]\n40:[\"$\",\"p\",\"134\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"After deploying SEO changes:\"}}]\n41:[\"$\",\"ol\",\"139\",{\"className\":\"list-decimal list-inside space-y-2 text-slate-600 my-4 text-sm leading-relaxed\",\"children\":[[\"$\",\"li\",\"0\",{\"dangerouslySetInnerHTML\":{\"__html\":\"Google Search Console → URL Inspection → verify meta tags.\"}}],[\"$\",\"li\",\"1\",{\"dangerouslySetInnerHTML\":{\"__html\":\"Google Rich Results Test → verify structured data.\"}}],[\"$\",\"li\",\"2\",{\"dangerouslySetInnerHTML\":{\"__html\":\"PageSpeed Insights (pagespeed.web.dev) → measure Core Web Vitals.\"}}],[\"$\",\"li\",\"3\",{\"dangerouslySetInnerHTML\":{\"__html\":\"Screaming Frog or Ahrefs → crawl the sitemap, check for broken canonical tags, duplicate meta descriptions.\"}}]]}]\n42:[\"$\",\"p\",\"140\",{\"className\":\"text-slate-600 leading-relaxed my-4 text-sm\",\"dangerouslySetInnerHTML\":{\"__html\":\"The most impactful single change for most Odoo websites is image size reduction. Odoo's drag-and-drop editor makes it easy to upload 4 MB PNGs that appear as 300 px thumbnails.\"}}]\n"])</script><script>self.__next_f.push([1,"43:[\"$\",\"div\",null,{\"className\":\"mt-10 flex items-center gap-3\",\"children\":[[\"$\",\"span\",null,{\"className\":\"text-xs text-slate-400\",\"children\":\"Share\"}],[\"$\",\"a\",null,{\"href\":\"https://twitter.com/intent/tweet?text=Odoo%20website%20SEO%3A%20meta%20tags%2C%20JSON-LD%20structured%20data%2C%20sitemap%2C%20and%20page%20speed\u0026url=https%3A%2F%2Ferpeek.ai%2Fblog%2Fodoo-website-seo-structured-data-sitemap\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"className\":\"inline-flex items-center gap-1.5 px-2.5 py-1 rounded text-xs font-medium text-slate-600 bg-slate-100 hover:bg-slate-200 transition-colors\",\"children\":[[\"$\",\"svg\",null,{\"className\":\"w-3.5 h-3.5\",\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"children\":[\"$\",\"path\",null,{\"d\":\"M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.74l7.73-8.835L1.254 2.25H8.08l4.253 5.622zm-1.161 17.52h1.833L7.084 4.126H5.117z\"}]}],\"X\"]}],[\"$\",\"a\",null,{\"href\":\"https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Ferpeek.ai%2Fblog%2Fodoo-website-seo-structured-data-sitemap\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"className\":\"inline-flex items-center gap-1.5 px-2.5 py-1 rounded text-xs font-medium text-slate-600 bg-slate-100 hover:bg-slate-200 transition-colors\",\"children\":[[\"$\",\"svg\",null,{\"className\":\"w-3.5 h-3.5\",\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"children\":[\"$\",\"path\",null,{\"d\":\"M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 0 1-2.063-2.065 2.064 2.064 0 1 1 2.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z\"}]}],\"LinkedIn\"]}]]}]\n"])</script><script>self.__next_f.push([1,"44:[\"$\",\"div\",null,{\"className\":\"mt-10 pt-8 border-t border-slate-200\",\"children\":[[\"$\",\"p\",null,{\"className\":\"text-sm text-slate-500 mb-4\",\"children\":\"Try ERPeek on your own Odoo module - ask questions, scaffold tests, and explore your codebase in plain language.\"}],[\"$\",\"$L19\",null,{\"href\":\"/register\",\"className\":\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-primary-600 hover:bg-primary-700 rounded-lg transition-colors\",\"children\":[\"Get started free\",[\"$\",\"svg\",null,{\"className\":\"w-4 h-4\",\"fill\":\"none\",\"viewBox\":\"0 0 24 24\",\"strokeWidth\":2,\"stroke\":\"currentColor\",\"children\":[\"$\",\"path\",null,{\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"d\":\"M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3\"}]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"45:[\"$\",\"nav\",null,{\"aria-label\":\"Post navigation\",\"className\":\"flex items-stretch gap-4 mt-12 pt-8 border-t border-slate-200\",\"children\":[[\"$\",\"$L19\",null,{\"href\":\"/blog/odoo-server-actions-automated-business-logic\",\"className\":\"flex-1 group flex flex-col gap-1 p-4 rounded-lg border border-slate-200 hover:border-primary-300 hover:bg-primary-50 transition-colors\",\"children\":[[\"$\",\"span\",null,{\"className\":\"inline-flex items-center gap-1 text-xs text-slate-400 group-hover:text-primary-500 transition-colors\",\"children\":[[\"$\",\"svg\",null,{\"className\":\"w-3.5 h-3.5\",\"fill\":\"none\",\"viewBox\":\"0 0 24 24\",\"strokeWidth\":2,\"stroke\":\"currentColor\",\"children\":[\"$\",\"path\",null,{\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"d\":\"M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18\"}]}],\"Previous\"]}],[\"$\",\"span\",null,{\"className\":\"text-xs font-semibold text-slate-700 group-hover:text-primary-700 leading-snug line-clamp-2 transition-colors\",\"children\":\"Odoo server actions: when to use them instead of computed fields or OWL components\"}]]}],[\"$\",\"$L19\",null,{\"href\":\"/blog/odoo-reconciliation-bank-matching-rules\",\"className\":\"flex-1 group flex flex-col gap-1 p-4 rounded-lg border border-slate-200 hover:border-primary-300 hover:bg-primary-50 transition-colors text-right\",\"children\":[[\"$\",\"span\",null,{\"className\":\"inline-flex items-center justify-end gap-1 text-xs text-slate-400 group-hover:text-primary-500 transition-colors\",\"children\":[\"Next\",[\"$\",\"svg\",null,{\"className\":\"w-3.5 h-3.5\",\"fill\":\"none\",\"viewBox\":\"0 0 24 24\",\"strokeWidth\":2,\"stroke\":\"currentColor\",\"children\":[\"$\",\"path\",null,{\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"d\":\"M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3\"}]}]]}],[\"$\",\"span\",null,{\"className\":\"text-xs font-semibold text-slate-700 group-hover:text-primary-700 leading-snug line-clamp-2 transition-colors\",\"children\":\"Odoo bank reconciliation: matching rules, statement import, and reconciliation models\"}]]}]]}]\n"])</script><script>self.__next_f.push([1,"46:[\"$\",\"div\",null,{\"className\":\"mt-16 pt-10 border-t border-slate-200\",\"children\":[[\"$\",\"h2\",null,{\"className\":\"text-base font-semibold text-slate-900 mb-6\",\"children\":\"Related articles\"}],[\"$\",\"div\",null,{\"className\":\"space-y-6\",\"children\":[[\"$\",\"article\",\"odoo-pricing-explained\",{\"className\":\"group\",\"children\":[\"$\",\"$L19\",null,{\"href\":\"/blog/odoo-pricing-explained\",\"className\":\"block\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex items-center flex-wrap gap-2 mb-1\",\"children\":[[\"$\",\"span\",null,{\"className\":\"inline-block px-1.5 py-0.5 rounded text-xs font-medium bg-slate-100 text-slate-600\",\"children\":\"General\"}],[\"$\",\"span\",null,{\"className\":\"text-slate-300\",\"aria-hidden\":\"true\",\"children\":\"·\"}],[\"$\",\"time\",null,{\"className\":\"text-xs font-medium text-slate-400\",\"children\":\"August 24, 2026\"}],[\"$\",\"span\",null,{\"className\":\"text-slate-300\",\"aria-hidden\":\"true\",\"children\":\"·\"}],[\"$\",\"span\",null,{\"className\":\"text-xs text-slate-400\",\"children\":[9,\" min\"]}]]}],[\"$\",\"h3\",null,{\"className\":\"text-sm font-semibold text-slate-900 group-hover:text-primary-600 transition-colors mb-1.5 leading-snug\",\"children\":\"Odoo Pricing Explained: Users, Apps, and What Your Bill Actually Covers\"}],[\"$\",\"p\",null,{\"className\":\"text-xs text-slate-500 leading-relaxed line-clamp-2\",\"children\":\"A plain-language breakdown of how Odoo's pricing model works - per-user fees, app bundles, hosting choices, partner markup, and the line items that surprise first-time buyers.\"}],[\"$\",\"span\",null,{\"className\":\"inline-flex items-center gap-1 mt-2 text-xs font-medium text-primary-600 group-hover:text-primary-700 transition-colors\",\"children\":[\"Read article\",[\"$\",\"svg\",null,{\"className\":\"w-3 h-3\",\"fill\":\"none\",\"viewBox\":\"0 0 24 24\",\"strokeWidth\":2,\"stroke\":\"currentColor\",\"children\":[\"$\",\"path\",null,{\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"d\":\"M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3\"}]}]]}]]}]}],[\"$\",\"article\",\"odoo-vendor-bill-digitization-ocr\",{\"className\":\"group\",\"children\":[\"$\",\"$L19\",null,{\"href\":\"/blog/odoo-vendor-bill-digitization-ocr\",\"className\":\"block\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex items-center flex-wrap gap-2 mb-1\",\"children\":[[\"$\",\"span\",null,{\"className\":\"inline-block px-1.5 py-0.5 rounded text-xs font-medium bg-slate-100 text-slate-600\",\"children\":\"General\"}],[\"$\",\"span\",null,{\"className\":\"text-slate-300\",\"aria-hidden\":\"true\",\"children\":\"·\"}],[\"$\",\"time\",null,{\"className\":\"text-xs font-medium text-slate-400\",\"children\":\"August 10, 2026\"}],[\"$\",\"span\",null,{\"className\":\"text-slate-300\",\"aria-hidden\":\"true\",\"children\":\"·\"}],[\"$\",\"span\",null,{\"className\":\"text-xs text-slate-400\",\"children\":[9,\" min\"]}]]}],[\"$\",\"h3\",null,{\"className\":\"text-sm font-semibold text-slate-900 group-hover:text-primary-600 transition-colors mb-1.5 leading-snug\",\"children\":\"Odoo vendor bill digitization: AI-powered OCR, the accounting inbox, and automated coding\"}],[\"$\",\"p\",null,{\"className\":\"text-xs text-slate-500 leading-relaxed line-clamp-2\",\"children\":\"Odoo's digitization feature reads vendor bill PDFs and images with an OCR pipeline, extracts vendor, date, amount, and line items, then proposes a draft bill ready for validation. Here is how the feature works, what it requires, and how to configure it for reliable processing.\"}],[\"$\",\"span\",null,{\"className\":\"inline-flex items-center gap-1 mt-2 text-xs font-medium text-primary-600 group-hover:text-primary-700 transition-colors\",\"children\":[\"Read article\",[\"$\",\"svg\",null,{\"className\":\"w-3 h-3\",\"fill\":\"none\",\"viewBox\":\"0 0 24 24\",\"strokeWidth\":2,\"stroke\":\"currentColor\",\"children\":[\"$\",\"path\",null,{\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"d\":\"M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3\"}]}]]}]]}]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"47:[\"$\",\"$L8\",null,{}]\n12:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\nf:null\n"])</script><script>self.__next_f.push([1,"14:[[\"$\",\"title\",\"0\",{\"children\":\"Odoo website SEO: meta tags, JSON-LD structured data, sitemap, and page speed | ERPeek\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Odoo Website includes SEO tools for meta titles, descriptions, and XML sitemaps, but most structured data and Core Web Vitals optimization requires custom QWeb template overrides. Here is what works out of the box and what you must build.\"}],[\"$\",\"meta\",\"2\",{\"name\":\"author\",\"content\":\"ERPeek\"}],[\"$\",\"meta\",\"3\",{\"name\":\"keywords\",\"content\":\"Odoo code intelligence,Odoo AI assistant,Odoo codebase search,Odoo developer tools,Odoo ERP analysis,Odoo custom addon search,Odoo consultant tools,AI-powered Odoo,Odoo module documentation,Odoo code search\"}],[\"$\",\"meta\",\"4\",{\"name\":\"creator\",\"content\":\"ERPeek\"}],[\"$\",\"link\",\"5\",{\"rel\":\"canonical\",\"href\":\"https://erpeek.ai/blog/odoo-website-seo-structured-data-sitemap\"}],[\"$\",\"meta\",\"6\",{\"property\":\"og:title\",\"content\":\"Odoo website SEO: meta tags, JSON-LD structured data, sitemap, and page speed - ERPeek Blog\"}],[\"$\",\"meta\",\"7\",{\"property\":\"og:description\",\"content\":\"Odoo Website includes SEO tools for meta titles, descriptions, and XML sitemaps, but most structured data and Core Web Vitals optimization requires custom QWeb template overrides. Here is what works out of the box and what you must build.\"}],[\"$\",\"meta\",\"8\",{\"property\":\"og:url\",\"content\":\"https://erpeek.ai/blog/odoo-website-seo-structured-data-sitemap\"}],[\"$\",\"meta\",\"9\",{\"property\":\"og:image\",\"content\":\"https://erpeek.ai/og-image.png\"}],[\"$\",\"meta\",\"10\",{\"property\":\"og:image:width\",\"content\":\"1200\"}],[\"$\",\"meta\",\"11\",{\"property\":\"og:image:height\",\"content\":\"630\"}],[\"$\",\"meta\",\"12\",{\"property\":\"og:image:alt\",\"content\":\"Odoo website SEO: meta tags, JSON-LD structured data, sitemap, and page speed - ERPeek Blog\"}],[\"$\",\"meta\",\"13\",{\"property\":\"og:type\",\"content\":\"article\"}],[\"$\",\"meta\",\"14\",{\"property\":\"article:published_time\",\"content\":\"2026-08-17\"}],[\"$\",\"meta\",\"15\",{\"property\":\"article:author\",\"content\":\"https://erpeek.ai\"}],[\"$\",\"meta\",\"16\",{\"property\":\"article:section\",\"content\":\"General\"}],[\"$\",\"meta\",\"17\",{\"property\":\"article:tag\",\"content\":\"odoo website seo\"}],[\"$\",\"meta\",\"18\",{\"property\":\"article:tag\",\"content\":\"Odoo\"}],[\"$\",\"meta\",\"19\",{\"property\":\"article:tag\",\"content\":\"ERPeek\"}],[\"$\",\"meta\",\"20\",{\"name\":\"twitter:card\",\"content\":\"summary_large_image\"}],[\"$\",\"meta\",\"21\",{\"name\":\"twitter:title\",\"content\":\"Odoo website SEO: meta tags, JSON-LD structured data, sitemap, and page speed - ERPeek Blog\"}],[\"$\",\"meta\",\"22\",{\"name\":\"twitter:description\",\"content\":\"Odoo Website includes SEO tools for meta titles, descriptions, and XML sitemaps, but most structured data and Core Web Vitals optimization requires custom QWeb template overrides. Here is what works out of the box and what you must build.\"}],[\"$\",\"meta\",\"23\",{\"name\":\"twitter:image\",\"content\":\"https://erpeek.ai/og-image.png\"}],[\"$\",\"link\",\"24\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.2y_glxf71sq15.ico\",\"sizes\":\"16x16\",\"type\":\"image/x-icon\"}],[\"$\",\"link\",\"25\",{\"rel\":\"icon\",\"href\":\"/icon.png?icon.40_j--qgescl4.png\",\"sizes\":\"32x32\",\"type\":\"image/png\"}],[\"$\",\"link\",\"26\",{\"rel\":\"apple-touch-icon\",\"href\":\"/apple-icon.png?apple-icon.32_94tw_epfyj.png\",\"sizes\":\"180x180\",\"type\":\"image/png\"}],[\"$\",\"$L49\",\"27\",{}]]\n"])</script></body></html>