GuideMarch 13, 2026

Website Builder in Odoo 19:
Design a Professional Site Without Writing Code

INTRODUCTION

Your ERP Already Has a Website Builder. You Just Never Turned It On.

Most Odoo customers pay for a separate WordPress or Wix subscription to run their public website. They maintain two systems, two login credentials, two sets of analytics, and a fragile API bridge to sync products and contact forms back to the ERP. When the bridge breaks (and it always breaks), leads fall through the cracks and product pages show stale inventory counts.

Odoo 19's Website module eliminates that gap entirely. It ships a full drag-and-drop website builder that reads directly from the same database your Sales, Inventory, and Accounting modules use. Product pages pull live stock levels. Contact forms create leads in CRM instantly. Blog posts are indexed alongside your knowledge base. And the entire editing experience happens in a visual editor that requires zero HTML, CSS, or JavaScript knowledge.

This guide walks through the complete setup: installing the website module, choosing and customizing a theme, building pages with the drag-and-drop editor, configuring menus and forms, integrating the blog, enabling multi-language support, and using the built-in SEO tools to rank on Google. Every step uses the standard Odoo 19 UI with no custom code.

01

Installing the Website Module and Choosing a Theme in Odoo 19

The Website module is not installed by default on new Odoo 19 databases. You need to activate it explicitly, choose a theme, and configure the basic site identity before you can start building pages.

Step 1: Install the Website Module

Navigate to Apps, search for "Website," and click Install. This pulls in the core website module plus its dependencies: portal, web_editor, http_routing, and web_unsplash (free stock photos from Unsplash built right into the editor).

Shell — CLI install (if you prefer the terminal)
# Install website module via CLI
./odoo-bin -c /etc/odoo/odoo.conf \
  -d your_database \
  -i website \
  --stop-after-init

# Verify installation
./odoo-bin shell -c /etc/odoo/odoo.conf -d your_database <<EOF
modules = env['ir.module.module'].search([
    ('name', 'in', ['website', 'web_editor', 'portal']),
    ('state', '=', 'installed')
])
for m in modules:
    print(f"{{m.name}} - {{m.state}} (v{{m.installed_version}})")
EOF

Step 2: Select a Theme

After installation, Odoo redirects you to the theme picker. Odoo 19 ships with 12 built-in themes organized by industry. Each theme is an installable module that overrides CSS variables, default building blocks, and page layouts. You can switch themes later, but it will reset page-level style overrides.

ThemeBest ForKey Features
DefaultClean, minimal sitesNeutral typography, highly customizable, lightest CSS footprint
StarterB2B companies, consultanciesProfessional header, feature grids, testimonial blocks
GrapheneTech companies, SaaSDark mode support, code-friendly typography, gradient sections
NanoE-commerce, retailProduct-focused layouts, large hero images, cart-optimized navigation
AviatoTravel, hospitalityFull-width imagery, booking-oriented CTAs, parallax scrolling

Step 3: Configure Site Identity

Go to Website → Configuration → Settings. Set your company name, logo, favicon, default language, and social media links. These values propagate to the header, footer, and structured data across every page.

Python — Programmatic site identity setup
# Set website identity via shell
website = env['website'].browse(1)
website.write({
    'name': 'My Company Website',
    'domain': 'https://www.mycompany.com',
    'social_facebook': 'https://facebook.com/mycompany',
    'social_linkedin': 'https://linkedin.com/company/mycompany',
    'social_twitter': 'https://x.com/mycompany',
    'google_analytics_key': 'G-XXXXXXXXXX',
    'plausible_shared_key': '',  # Alternative to GA
})
env.cr.commit()
Custom Domain Setup

In Website → Configuration → Settings → Domain, enter your custom domain (e.g., www.mycompany.com). Odoo uses this for canonical URLs, sitemap generation, and social sharing previews. If you run multiple websites (multi-website mode), each site gets its own domain. DNS must point to your Odoo server, and Nginx should terminate SSL before proxying to Odoo.

02

Using the Odoo 19 Drag-and-Drop Editor: Building Blocks, Columns, and Styling

The website editor in Odoo 19 is a WYSIWYG page builder that runs directly in the browser. Click Edit on any page to enter edit mode. The left panel shows a library of pre-built building blocks you can drag onto the page canvas. Every block is fully configurable: colors, spacing, animations, visibility rules, and responsive behavior.

Building Block Categories

CategoryBlock CountExamples
Structure18Banner, Cover, Text-Image, Columns, Separator, Masonry Grid
Features14Steps, Comparisons, Accordion FAQ, Tabs, Timeline, Counters
Dynamic Content8Blog Posts, Products, Events, Team Members, Testimonials, Pricing
Inner Content12Buttons, Badges, Cards, Alerts, Progress Bars, Social Icons

Step 1: Add a Hero Section

Drag a Cover block onto the top of your page. Click the background to set an image (upload your own or pick from the built-in Unsplash integration). Double-click the text to edit the headline and subtitle. Use the toolbar to adjust font size, weight, and color.

Step 2: Build a Feature Grid

Drag a Columns block below the hero. Select 3 or 4 columns. Each column can contain an icon, heading, and description. Click any element to customize. The Style tab on the right panel lets you set padding, margin, background color, border radius, and shadow for any element.

Step 3: Theme Customization via the Style Panel

Click the paintbrush icon in the top toolbar to open the global Theme Customizer. This panel controls site-wide variables without touching CSS:

SCSS — What the Theme Customizer generates under the hood
// These variables are set via the visual UI
// Stored in website.theme_customize_asset
$o-color-1: #1B3A4B;       // Primary brand color
$o-color-2: #065A82;       // Secondary color
$o-color-3: #1C7293;       // Accent color
$o-color-4: #F4F4F4;       // Light background
$o-color-5: #FFFFFF;       // White

$font-family-base: 'Inter', sans-serif;
$headings-font-family: 'Plus Jakarta Sans', sans-serif;
$font-size-base: 1rem;     // 16px
$h1-font-size: 3.25rem;    // 52px
$btn-border-radius: 0.5rem;
$navbar-height: 72px;

// Button styles
$btn-primary-color: $o-color-1;
$btn-primary-bg: $o-color-3;
$btn-primary-border-color: $o-color-3;

Every change you make in the Theme Customizer updates these SCSS variables. Odoo recompiles the CSS on save. This means your color and font choices cascade automatically across the header, footer, buttons, links, and all building blocks on every page.

Responsive Preview

In edit mode, use the device icons in the top toolbar to preview your page on desktop, tablet, and mobile viewports. Odoo 19 building blocks are responsive by default, but you can set per-device visibility on any element: right-click a block, select Visibility, and choose which breakpoints it appears on. This lets you show a compact mobile layout while keeping a full-width desktop version.

04

Building Contact Forms and Integrating the Blog in Odoo 19 Website

Contact Forms That Create CRM Leads

The Form Builder block in the website editor creates forms that write directly to Odoo models. No Zapier, no webhooks, no middleware. Drag a Form block onto any page, and configure where submissions go:

ActionTarget ModelWhat Happens on Submit
Create an Opportunitycrm.leadNew lead in your CRM pipeline with all form fields mapped to lead fields
Create a Tickethelpdesk.ticketNew support ticket assigned to the default helpdesk team
Subscribe to Newslettermailing.contactAdds the email to a mailing list for email marketing campaigns
Create a Taskproject.taskNew task in a specified project (useful for internal request forms)
Send an EmailN/ASends form data as an email to specified recipients (no record created)

Step 1: Build a Lead Capture Form

Drag a Form block onto your Contact page. In the form settings (click the form, then the settings icon), select "Create an Opportunity" as the action. Add fields by clicking + Add a field. Map each form field to a CRM lead field:

XML — Form structure generated by the editor (simplified)
<section class="s_website_form" data-snippet="s_website_form">
  <form action="/website/form/"
        method="post"
        data-model_name="crm.lead"
        data-success_mode="redirect"
        data-success_page="/thank-you">

    <!-- Hidden field: assign to Sales Team -->
    <input type="hidden"
           name="team_id"
           value="1"/>

    <!-- Visible fields -->
    <div class="s_website_form_field">
      <label for="contact_name">Your Name</label>
      <input type="text"
             name="contact_name"
             required="required"/>
    </div>

    <div class="s_website_form_field">
      <label for="email_from">Email</label>
      <input type="email"
             name="email_from"
             required="required"/>
    </div>

    <div class="s_website_form_field">
      <label for="phone">Phone</label>
      <input type="tel"
             name="phone"/>
    </div>

    <div class="s_website_form_field">
      <label for="description">Message</label>
      <textarea name="description"
                rows="4"></textarea>
    </div>

    <button type="submit" class="btn btn-primary">
      Send Message
    </button>
  </form>
</section>
reCAPTCHA Protection

Go to Website → Configuration → Settings → Privacy and enter your Google reCAPTCHA v3 Site Key and Secret Key. Once configured, every website form automatically includes invisible reCAPTCHA validation. Without this, your CRM will fill up with spam leads within days of going live.

Blog Integration

Install the Website Blog module (website_blog) from the Apps menu. This adds a /blog section to your site with:

  • Multiple blogs: Create separate blogs for News, Product Updates, Industry Insights, etc.
  • Rich editor: Write posts using the same drag-and-drop editor as pages. Add code blocks, image galleries, embedded videos, and call-to-action building blocks.
  • Tags and categories: Organize posts with tags. Visitors can filter by tag. Tags are included in structured data for Google.
  • Author profiles: Each post shows the author with avatar, bio, and link to their other posts.
  • Cover images: Used for blog listing cards, social sharing previews, and RSS feed.
  • Comments: Optional. Enable per-blog via settings. Comments are moderated by default.
Shell — Install blog and create a post programmatically
# Install blog module
./odoo-bin -c /etc/odoo/odoo.conf \
  -d your_database \
  -i website_blog \
  --stop-after-init

# Create a blog post via shell
./odoo-bin shell -c /etc/odoo/odoo.conf -d your_database <<EOF
blog = env['blog.blog'].search([], limit=1)
post = env['blog.post'].create({
    'name': 'Welcome to Our New Website',
    'blog_id': blog.id,
    'subtitle': 'Built with Odoo 19 Website Builder',
    'content': '<p>We are excited to launch...</p>',
    'tag_ids': [(0, 0, {'name': 'Company News'})],
    'website_published': True,
})
print(f"Created: {{post.name}} at /blog/{{post.blog_id.name}}/{{post.id}}")
env.cr.commit()
EOF

Dynamic Blog Blocks on Other Pages

You can embed live blog post cards on any page. In the editor, drag the Blog Posts dynamic block onto your homepage. Configure it to show the 3 latest posts, filter by tag, or pin specific posts. The block updates automatically when new posts are published.

05

Setting Up Multi-Language Websites in Odoo 19

Odoo 19 handles multi-language at the framework level, not as an afterthought plugin. Every text field in the database supports translations. The website module extends this to pages, menus, building blocks, blog posts, and SEO metadata.

Step 1: Activate Languages

Go to Settings → General Settings → Languages. Click "Add a Language" and select from the 50+ languages Odoo ships with. Each activated language gets a URL prefix: /en, /fr, /es, /ar.

Python — Activate languages programmatically
# Activate French and Arabic
for lang_code in ['fr_FR', 'ar_001']:
    lang = env['res.lang']._activate_lang(lang_code)
    print(f"Activated: {{lang.name}} ({{lang.code}})")

# Set website languages
website = env['website'].browse(1)
langs = env['res.lang'].search([
    ('code', 'in', ['en_US', 'fr_FR', 'ar_001'])
])
website.language_ids = langs
website.default_lang_id = env.ref('base.lang_en')
env.cr.commit()

Step 2: Translate Website Content

Switch to the target language using the language selector in the website header. Enter edit mode. Every text element shows the original text with a translation indicator. Click the text and type the translation directly in the editor. Odoo stores the translation in ir.translation linked to the original element.

Step 3: SEO Metadata Per Language

Each language version of a page has its own meta title, meta description, and Open Graph data. Switch to the target language, open the SEO panel (Promote tab), and enter localized metadata. Odoo 19 automatically generates hreflang tags linking all language versions:

HTML — Auto-generated hreflang tags
<!-- Odoo 19 generates these automatically -->
<link rel="alternate" hreflang="en"
      href="https://www.mycompany.com/en/services"/>
<link rel="alternate" hreflang="fr"
      href="https://www.mycompany.com/fr/services"/>
<link rel="alternate" hreflang="ar"
      href="https://www.mycompany.com/ar/services"/>
<link rel="alternate" hreflang="x-default"
      href="https://www.mycompany.com/en/services"/>
RTL Language Support

Odoo 19 automatically switches to RTL layout for Arabic, Hebrew, and other RTL languages. The CSS direction: rtl is applied at the <html> level, and building blocks mirror their flex/grid layout. You do not need to create separate pages. However, test your custom CSS overrides in RTL mode because hardcoded margin-left or padding-right values do not auto-flip.

06

Odoo 19 Built-In SEO Tools: Meta Tags, Sitemap, Structured Data, and URL Management

Odoo 19 ships with a comprehensive SEO toolkit built into the website editor. It covers the basics most businesses need without requiring Yoast, RankMath, or any third-party SEO plugin.

The SEO Panel (Promote Tab)

While editing any page, click the "Promote" tab in the top toolbar. This opens the SEO panel where you configure:

  • Meta Title: Custom title tag (defaults to page name + site name). Keep it under 60 characters.
  • Meta Description: Custom description shown in search results. Keep it under 155 characters.
  • URL Slug: Edit the page URL directly. Odoo creates a 301 redirect from the old URL automatically.
  • Keyword Analysis: Enter a target keyword and Odoo scans the page for keyword density in the title, headings, body text, image alt tags, and URL.
  • Social Preview: Preview how the page will look when shared on Google, Facebook, and Twitter/X.

Automatic Sitemap

Odoo 19 auto-generates a /sitemap.xml that includes all published pages, blog posts, product pages, and event pages. It updates dynamically as you publish or unpublish content. Submit this to Google Search Console.

XML — Example sitemap output
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
        xmlns:xhtml="http://www.w3.org/1999/xhtml">
  <url>
    <loc>https://www.mycompany.com/services</loc>
    <lastmod>2026-03-10</lastmod>
    <priority>0.8</priority>
    <!-- Multi-language alternates -->
    <xhtml:link rel="alternate" hreflang="en"
                href="https://www.mycompany.com/en/services"/>
    <xhtml:link rel="alternate" hreflang="fr"
                href="https://www.mycompany.com/fr/services"/>
  </url>
  <url>
    <loc>https://www.mycompany.com/blog/news/welcome-post-1</loc>
    <lastmod>2026-03-12</lastmod>
    <priority>0.6</priority>
  </url>
</urlset>

Structured Data (JSON-LD)

Odoo 19 automatically injects JSON-LD structured data for key page types:

Page TypeSchema TypeIncluded Fields
HomepageOrganizationName, logo, URL, social profiles, contact info
Product pageProductName, price, currency, availability, images, ratings
Blog postArticleHeadline, author, date, image, description
EventEventName, date, location, ticket price, organizer
All pagesBreadcrumbListHierarchical breadcrumb path

URL Redirects

Go to Website → Configuration → Redirects to manage URL redirects. You can create 301 (permanent), 302 (temporary), or 404 (gone) redirects. Odoo auto-creates 301 redirects when you change a page's URL slug via the SEO panel. This prevents broken links after restructuring your site.

Python — Bulk-create redirects (e.g., after a site migration)
# Redirect old WordPress URLs to new Odoo pages
redirects = [
    ('/about-us/',        '/about'),
    ('/services/erp/',    '/services/odoo-implementation'),
    ('/blog/2025/01/01/', '/blog/news/old-post-1'),
    ('/contact-us.html',  '/contact-us'),
]

for old_url, new_url in redirects:
    env['website.rewrite'].create({
        'name': f'Redirect {{old_url}}',
        'url_from': old_url,
        'url_to': new_url,
        'redirect_type': '301',
        'website_id': 1,
    })
    print(f"301: {{old_url}} -> {{new_url}}")

env.cr.commit()
Google Search Console Integration

Odoo 19 does not have a native Search Console API integration. However, you can verify site ownership by adding the Google verification meta tag in Website → Configuration → Settings → SEO. For ongoing monitoring, submit your /sitemap.xml URL and check the Coverage report weekly for crawl errors, especially after publishing new pages or changing URL slugs.

07

5 Odoo 19 Website Builder Mistakes That Kill Your SEO and User Experience

1

Forgetting to Set Image Alt Text on Every Building Block

The drag-and-drop editor makes it effortless to add images, but the alt text field defaults to the filename (e.g., IMG_20260310_143022.jpg). Google uses alt text to understand image content, and screen readers depend on it for accessibility. A site with 50 images and no alt text is penalized in both Core Web Vitals accessibility audits and image search rankings.

Our Fix

Click every image in edit mode and set a descriptive alt text in the image options panel. Include your target keyword where natural. For decorative images (backgrounds, dividers), set alt to empty (alt="") so screen readers skip them. Audit with Lighthouse before publishing.

2

Publishing Pages Without Configuring the Meta Description

If you skip the Promote tab and publish directly, Odoo uses the first ~155 characters of visible body text as the meta description. For pages that start with a building block like a counter or icon grid, this produces gibberish in search results: "24/7 99.9% 500+ Contact us today for a free..." This tanks your click-through rate.

Our Fix

Make the Promote tab part of your publishing checklist. Before toggling a page live, set a custom meta title and meta description that includes your target keyword and a clear call-to-action. Use the Social Preview section to verify how the page will appear in Google and on social media.

3

Using Too Many Building Blocks and Bloating Page Load Time

Each building block loads its own CSS and JavaScript snippets. A page with 30+ blocks can generate 200+ DOM elements and 500KB+ of CSS. Core Web Vitals' Largest Contentful Paint (LCP) score drops below the "Good" threshold, and Google will rank the page lower on mobile results. We have seen Odoo websites with 4-second LCP scores simply because the homepage had 40 building blocks.

Our Fix

Limit your homepage to 8-12 building blocks. Use the browser DevTools Network tab to measure total transferred size. Enable Nginx gzip compression (see our Nginx reverse proxy guide) and set aggressive cache headers on static assets. Target LCP under 2.5 seconds.

4

Not Enabling CDN for Static Assets

By default, Odoo serves images, CSS, and JavaScript from the same origin server. If your audience is global, users in Asia hitting a European server experience 300-500ms of additional latency per asset. With 50 assets per page load, that adds up to seconds of unnecessary wait time.

Our Fix

Go to Website → Configuration → Settings → CDN. Enter your CDN base URL (e.g., https://cdn.mycompany.com). Odoo rewrites all static asset URLs to point to the CDN. Cloudflare, AWS CloudFront, and BunnyCDN all work. Configure the CDN to pull from your origin on cache miss.

5

Switching Themes After Building Pages

Themes in Odoo are installable modules that override SCSS variables and default building block styles. When you switch themes on a site with existing pages, per-block style overrides can conflict with the new theme's defaults. Background colors, font sizes, and spacing values you set manually may render differently. In the worst case, custom CSS classes from the old theme produce unstyled blocks.

Our Fix

Choose your theme before building pages, not after. If you must switch, do it on a staging copy first and review every page. Pay special attention to pages with custom colors and spacing. The Default theme is the safest starting point because it has the smallest CSS footprint and the fewest opinionated overrides.

BUSINESS ROI

What Consolidating Your Website into Odoo Saves Your Business

The ROI of using Odoo's website builder is not just about saving on a WordPress license. It is about eliminating the integration layer between your public website and your business operations:

$0Integration Cost

No Zapier, no webhook middleware, no API syncs. Forms create CRM leads instantly. Product pages show live inventory. The website and ERP share one database.

100%Lead Capture Rate

Every form submission writes directly to crm.lead. No middleware failures, no lost submissions, no "the Zapier zap stopped running 3 weeks ago" surprises.

1 LoginFor Everything

Marketing edits the website, Sales views the leads, Support sees the tickets. All in one system with one set of user permissions. No context-switching between tools.

Beyond cost savings, there is a speed advantage. When your marketing team can publish a new landing page, attach a lead capture form, and see the resulting CRM leads in the same system — all within 30 minutes — your campaign cycle time drops from weeks to hours. That speed compounds over every product launch, event, and seasonal promotion.

SEO NOTES

Optimization Metadata

Meta Desc

Complete guide to the Odoo 19 Website Builder. Drag-and-drop editor, theme customization, forms, blog, multi-language, and SEO tools. No code required.

H2 Keywords

1. "Installing the Website Module and Choosing a Theme in Odoo 19"
2. "Using the Odoo 19 Drag-and-Drop Editor: Building Blocks, Columns, and Styling"
3. "Building Contact Forms and Integrating the Blog in Odoo 19 Website"
4. "Odoo 19 Built-In SEO Tools: Meta Tags, Sitemap, Structured Data, and URL Management"
5. "5 Odoo 19 Website Builder Mistakes That Kill Your SEO and User Experience"

Stop Paying for a Website That Does Not Talk to Your ERP

Every external website integration is a point of failure between your customers and your operations. A form submission that does not reach CRM is a lost sale. A product page showing "In Stock" when the warehouse is empty is a disappointed customer. A blog that lives on a different domain splits your SEO authority in half.

Odoo 19's website builder eliminates every one of these gaps. It is not the most feature-rich page builder on the market, but it is the only one that shares a database with your entire business. For most SMBs, that single advantage outweighs any limitation in the visual editor.

If you need help migrating your existing website to Odoo 19 or setting up a multi-language, SEO-optimized site from scratch, we can help. We handle theme selection, page architecture, SEO migration (including redirect mapping from your old site), and training for your marketing team to self-manage the site going forward.

Book a Free Website Consultation