Bạn dựng một trang tùy biến bằng controller — trang ưu đãi, trang tra cứu. Nó chạy tốt. Nhưng vài tuần sau nhận ra Google chưa hề index nó: trang không có trong sitemap.xml, <title> trơ trọi, không thẻ meta mô tả. Lý do đơn giản: route tự viết không tự động vào sitemap hay có SEO — Odoo cần bạn khai. Bài này chỉ cách làm đúng: sitemap=True để route vào sitemap.xml, callback cho URL động, và đặt title/meta/OG qua website.layout — tất cả kiểm chứng bằng sitemap.xml và thẻ <head> thật trên Odoo 19.
sitemap=True: đưa route vào sitemap.xml
Odoo tự sinh /sitemap.xml từ hai nguồn: các website.page đã đăng, và các route controller có khai sitemap. Route của bạn phải nói rõ nó có muốn vào sitemap không — bằng tham số sitemap trong @http.route.

Hình 1: Ba kiểu khai sitemap. sitemap=True — URL tĩnh vào sitemap. sitemap=False — route không vào (trang nội bộ, API). sitemap=<hàm callback> — cho URL động có tham số (như /the/<id>): Odoo gọi hàm để tự liệt kê từng URL cụ thể. Lưu ý Odoo 19 cảnh báo nếu route website bỏ trống hẳn tham số sitemap — nên luôn khai rõ.
Curl thật /sitemap.xml sau khi thêm route, nó xuất hiện ngay:

Hình 2: robots.txt trỏ crawler tới sitemap.xml; sitemap.xml liệt kê mọi trang công khai. Sau khi thêm route sitemap=True, /quan_ca_phe/uu-dai xuất hiện — tổng từ 20 lên 21 URL. Lưu ý: sitemap được cache 12 giờ (lưu trong một ir.attachment), nên thay đổi không hiện ngay — xoá cache để thấy liền khi test.
Đặt title, meta description và Open Graph
Vào được sitemap là để Google tìm thấy; còn để Google hiểu và hiển thị đẹp thì cần thẻ meta. website.layout đọc vài biến từ giá trị controller truyền vào để dựng <head>:
additional_title→<title>(thành"<additional_title> | <tên website>").website_meta_description→<meta name="description">(đoạn mô tả Google hiện dưới tiêu đề).website_meta_keywords→<meta name="keywords">.
Và từ những cái đó, website.layout tự sinh luôn thẻ Open Graph (og:title, og:url, og:image...) để chia sẻ lên Facebook/Zalo hiện thumbnail đẹp. Curl trang và xem <head> thật:

Hình 3: Thẻ <head> thật. <title> và <meta name="description"> đúng những gì controller truyền; og:type, og:title, og:url, og:image do website.layout tự sinh. Chỉ cần truyền additional_title + website_meta_description, phần còn lại Odoo lo.
Chi tiết đáng nhớ
- Cache sitemap 12 giờ.
sitemap.xmlđược sinh rồi cache trong mộtir.attachment(12h). Trang mới sẽ vào sitemap nhưng có độ trễ — bình thường không sao (Google cũng không crawl liên tục), chỉ khi test mới cần xoá cache để thấy ngay. - Chỉ trang công khai mới nên vào sitemap.
sitemap=Truecho trangauth='public'thật sự công khai; trang cần đăng nhập (auth='user') đặtsitemap=False— đưa vào sitemap chỉ khiến Google gặp trang chuyển hướng đăng nhập. - URL động cần callback. Route có tham số (
/the/<id>) không thể chỉsitemap=True(Odoo không biết những id nào tồn tại) — phải viết hàm callbackyieldtừng{'loc': ...}. - website.page thì tự động. Trang khai bằng XML (như phần 170) tự vào sitemap nếu
website_published=Truevàwebsite_indexed=True— không cần code. - Dữ liệu có cấu trúc (JSON-LD). Muốn rich snippet (sao đánh giá, giá...), thêm
<script type="application/ld+json">trong template với schema.org phù hợp — Odoo không tự sinh cái này cho trang tùy biến.
Ba ý mang về
- Route tùy biến không tự vào sitemap — khai
sitemap=True(URL tĩnh),sitemap=<callback>(URL động,yieldtừng loc), hoặcsitemap=False(không index); Odoo 19 cảnh báo nếu bỏ trống hẳn. - SEO meta đặt qua giá trị controller mà
website.layoutđọc:additional_title(title),website_meta_description,website_meta_keywords— và OG tags được tự sinh từ đó. sitemap.xmlcache 12 giờ (trongir.attachment);robots.txttrỏ tới nó;website.pagecông khai + indexed tự vào sitemap; URL động và JSON-LD thì phải tự lo.
Ta đã lo phần máy tìm kiếm. Phần sau quay lại phía người dùng thật: cách gắn trang tùy biến vào điều hướng của website. Phần sau nói về website menu và page quản lý — thêm mục vào thanh menu, tổ chức các trang, và cho người quản trị bật/tắt, sắp xếp chúng ngay trên giao diện.