{"id":710,"date":"2023-05-31T14:13:57","date_gmt":"2023-05-31T11:13:57","guid":{"rendered":"https:\/\/presta.site\/blog\/?p=710"},"modified":"2026-07-24T16:14:25","modified_gmt":"2026-07-24T13:14:25","slug":"solving-prestashop-seo-url-rewriting-problems","status":"publish","type":"post","link":"https:\/\/presta.site\/blog\/en\/solving-prestashop-seo-url-rewriting-problems\/","title":{"rendered":"PrestaShop URL Rewriting: 5-Step Checklist for Fixing Broken Friendly URLs"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Friendly URL is on, yet product links still look like <code class=\"codecolorer text default\"><span class=\"text\">index.php?id_product=12<\/span><\/code> &#8211; or every pretty path returns 404. <strong>PrestaShop URL rewriting<\/strong> only works when the Back Office toggle, the root rewrite file (Apache), and the web server rules agree. This is a 5-step checklist: pick your symptom, confirm the shop setting, fix the server layer, prove one URL, then clean duplicates and old 404s.<\/p>\n\n\n<!--more-->\n\n\n<p class=\"wp-block-paragraph\">Generic \u201cenable Friendly URL\u201d advice is easy to get from a chatbot. What usually wastes hours is running the wrong fix for your symptom &#8211; or skipping the pass\/fail check after each step. Work the list in order. Official labels are under <a href=\"https:\/\/docs.prestashop-project.org\/v.9-documentation\/user-guide\/configuring-shop\/shop-parameters\/traffic\" target=\"_blank\" rel=\"noopener noreferrer\">Shop Parameters \u2192 Traffic<\/a> in the PrestaShop 9 docs. Before you edit server config, take a <a href=\"https:\/\/presta.site\/blog\/en\/how-to-create-a-backup-in-prestashop\/\">full PrestaShop backup<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1 &#8211; Name what is broken<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Open a product page in a private window and note which case you have. Do not skip this &#8211; the three cases need different fixes.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>A &#8211; Ugly URLs still.<\/strong> The address bar still shows <code class=\"codecolorer text default\"><span class=\"text\">id_product<\/span><\/code>, <code class=\"codecolorer text default\"><span class=\"text\">id_category<\/span><\/code>, or <code class=\"codecolorer text default\"><span class=\"text\">controller=<\/span><\/code> after you enabled Friendly URL. PrestaShop is not emitting rewritten links (or cache is serving an old page).<\/li>\n<li><strong>B &#8211; Pretty URLs 404.<\/strong> Links look correct (<code class=\"codecolorer text default\"><span class=\"text\">\/category\/product-slug<\/span><\/code>) but every pretty path returns Not Found. The shop is generating slugs; the web server is not routing them into PrestaShop.<\/li>\n<li><strong>C &#8211; Works on one domain only.<\/strong> The main shop is fine; a multistore domain, subdomain, or subdirectory shop fails. That is often shop URL \/ DNS \/ document root &#8211; not a second Friendly URL bug. See our <a href=\"https:\/\/presta.site\/blog\/en\/prestashop-multistore\/\">PrestaShop multistore guide<\/a> in parallel with this checklist.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Pass:<\/strong> you can point to A, B, or C before you touch Apache or Nginx.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2 &#8211; Confirm Friendly URL in the Back Office<\/h2>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"412\" src=\"https:\/\/presta.site\/blog\/wp-content\/uploads\/2023\/05\/Screenshot_1-5-1024x412.png\" alt=\"PrestaShop URL rewriting Friendly URL toggle under Shop Parameters Traffic and SEO\" class=\"wp-image-716\" srcset=\"https:\/\/presta.site\/blog\/wp-content\/uploads\/2023\/05\/Screenshot_1-5-1024x412.png 1024w, https:\/\/presta.site\/blog\/wp-content\/uploads\/2023\/05\/Screenshot_1-5-300x121.png 300w, https:\/\/presta.site\/blog\/wp-content\/uploads\/2023\/05\/Screenshot_1-5-768x309.png 768w, https:\/\/presta.site\/blog\/wp-content\/uploads\/2023\/05\/Screenshot_1-5.png 1381w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Go to <strong>Shop Parameters \u2192 Traffic &amp; SEO<\/strong>.<\/li>\n<li>Open <strong>Set up URLs<\/strong>.<\/li>\n<li>Set <strong>Friendly URL<\/strong> to Yes and save.<\/li>\n<li>Clear PrestaShop cache (<strong>Advanced Parameters \u2192 Performance<\/strong>) and retest the same product in a private window.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">On Apache, saving this page should create or refresh the root <code class=\"codecolorer text default\"><span class=\"text\">.htaccess<\/span><\/code> with PrestaShop rewrite rules. If the file is missing, empty, or older than your save, PHP cannot write the shop root &#8211; fix ownership\/permissions before you chase modules.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">On Nginx, the toggle alone never installs rewrite rules. You still need Step 3.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Pass (case A):<\/strong> after cache clear, new HTML links use slugs (even if those slugs still 404 &#8211; that becomes case B). <strong>Pass (case B\/C):<\/strong> Friendly URL is Yes and stays Yes after reload.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3 &#8211; Fix the server layer (Apache or Nginx)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check <strong>Advanced Parameters \u2192 Information \u2192 Server information<\/strong> (or ask the host). Follow only the branch that matches your server.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">If you are on Apache<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Enable <code class=\"codecolorer text default\"><span class=\"text\">mod_rewrite<\/span><\/code> (often on by default).<\/li>\n<li>Confirm the shop document root has a readable <code class=\"codecolorer text default\"><span class=\"text\">.htaccess<\/span><\/code> that PrestaShop updated on the last SEO save.<\/li>\n<li>AllowOverrides must permit rewrite directives for that directory.<\/li>\n<li>Subdirectory installs need a matching <code class=\"codecolorer text default\"><span class=\"text\">RewriteBase<\/span><\/code>.<\/li>\n<li>Custom rules above PrestaShop\u2019s block can short-circuit rewriting &#8211; temporarily move extras below the PrestaShop section to test.<\/li>\n<li>After a manual edit, flip Friendly URL off\/on once and save so PrestaShop rewrites its own section, then re-add only the custom lines you still need.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Pass:<\/strong> pretty product URL returns HTTP 200 with the correct product (not the host\u2019s default 404 page).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">If you are on Nginx<\/h3>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"947\" height=\"220\" src=\"https:\/\/presta.site\/blog\/wp-content\/uploads\/2023\/05\/Screenshot_2-4.png\" alt=\"Nginx server block where PrestaShop URL rewriting rules belong\" class=\"wp-image-719\" srcset=\"https:\/\/presta.site\/blog\/wp-content\/uploads\/2023\/05\/Screenshot_2-4.png 947w, https:\/\/presta.site\/blog\/wp-content\/uploads\/2023\/05\/Screenshot_2-4-300x70.png 300w, https:\/\/presta.site\/blog\/wp-content\/uploads\/2023\/05\/Screenshot_2-4-768x178.png 768w, https:\/\/presta.site\/blog\/wp-content\/uploads\/2023\/05\/Screenshot_2-4-941x220.png 941w\" sizes=\"auto, (max-width: 947px) 100vw, 947px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Nginx ignores <code class=\"codecolorer text default\"><span class=\"text\">.htaccess<\/span><\/code>. Edit the site server block (often under <code class=\"codecolorer text default\"><span class=\"text\">\/etc\/nginx\/sites-available\/<\/span><\/code>):<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Add the current PrestaShop Nginx rewrite sample from the <a href=\"https:\/\/devdocs.prestashop-project.org\/9\/basics\/installation\/nginx\/\" target=\"_blank\" rel=\"noopener noreferrer\">PrestaShop 9 Nginx docs<\/a> (keep your real root and PHP-FPM socket).<\/li>\n<li>Run <code class=\"codecolorer text default\"><span class=\"text\">nginx -t<\/span><\/code>.<\/li>\n<li>If the test passes, reload: <code class=\"codecolorer text default\"><span class=\"text\">systemctl reload nginx<\/span><\/code> (or your host\u2019s control-panel equivalent).<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">If a chatbot pasted an old sample, replace it with the official block for your major version. Paths and <code class=\"codecolorer text default\"><span class=\"text\">try_files<\/span><\/code> lines drift; forum snippets from years ago are a common cause of case B.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Pass:<\/strong> same as Apache &#8211; pretty URL \u2192 200 \u2192 correct product. If a CDN or reverse proxy sat in front while you were broken, purge its cache once so it stops serving cached 404s.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4 &#8211; Prove PrestaShop URL rewriting end to end<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Do not stop at \u201clinks look pretty in the menu.\u201d Run this quick proof on one product:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Private window: open the product from the category listing.<\/li>\n<li>Address bar shows a slug path, not only <code class=\"codecolorer text default\"><span class=\"text\">id_product<\/span><\/code>.<\/li>\n<li>Copy that pretty URL, open it in a new tab: HTTP 200, same product.<\/li>\n<li>Optional: request a known wrong slug &#8211; you should get your shop 404 theme, not a blank web-server page that never hit PrestaShop.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">If Step 4 fails only on a second domain while the main domain passes, return to case C (multistore URL \/ DNS \/ document root) before editing rewrite rules again.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Pass:<\/strong> one product survives listing click + direct pretty URL reload.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5 &#8211; Canonicals and leftover 404s<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When rewriting works, finish the SEO side so search engines stop splitting equity across duplicates and dead paths.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>On <strong>Shop Parameters \u2192 Traffic &amp; SEO<\/strong>, set <strong>Redirect to the canonical URL<\/strong> to <strong>301 Moved Permanently<\/strong> on a live shop.<\/li>\n<li>Check third-party modules that add listing or blog URLs &#8211; they need matching canonicals too.<\/li>\n<li>After slug renames, category moves, or a domain change, add 301s from old paths (or restore the entity). Changing URL schema without redirects burns rankings you already earned.<\/li>\n<li>Submit an updated sitemap so crawlers pick up preferred URLs &#8211; see our <a href=\"https:\/\/presta.site\/blog\/en\/what-is-sitemap-and-how-to-work-with-it-in-prestashop\/\">PrestaShop sitemap guide<\/a>.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Use Search Console coverage (or access logs) to list real 404 paths still hitting the server. Fix those with redirects or content restores &#8211; rewriting alone will not revive deleted CMS pages.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Pass:<\/strong> canonical option is 301; a sample alternate product path redirects; known old slugs you care about are redirected or intentionally gone.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Quick recap of the 5 steps<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Name the symptom (A ugly \/ B pretty 404 \/ C one domain only).<\/li>\n<li>Confirm Friendly URL Yes + cache clear (+ writable <code class=\"codecolorer text default\"><span class=\"text\">.htaccess<\/span><\/code> on Apache).<\/li>\n<li>Fix Apache <code class=\"codecolorer text default\"><span class=\"text\">mod_rewrite<\/span><\/code>\/<code class=\"codecolorer text default\"><span class=\"text\">.htaccess<\/span><\/code> or Nginx server-block rules.<\/li>\n<li>Prove one product: pretty link + direct reload = 200.<\/li>\n<li>Set canonical 301s and clean leftover 404s \/ sitemap.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">If you only remember one habit: after every change, retest the same product URL before you open the next setting. That is how PrestaShop URL rewriting stops being a guessing loop.<\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>Broken Friendly URLs? Follow this 5-step PrestaShop URL rewriting checklist &#8211; symptom, Back Office toggle, Apache or Nginx, verify, then canonicals and leftover 404s.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[25],"tags":[],"class_list":["post-710","post","type-post","status-publish","format-standard","hentry","category-development"],"_links":{"self":[{"href":"https:\/\/presta.site\/blog\/wp-json\/wp\/v2\/posts\/710","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/presta.site\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/presta.site\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/presta.site\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/presta.site\/blog\/wp-json\/wp\/v2\/comments?post=710"}],"version-history":[{"count":11,"href":"https:\/\/presta.site\/blog\/wp-json\/wp\/v2\/posts\/710\/revisions"}],"predecessor-version":[{"id":1986,"href":"https:\/\/presta.site\/blog\/wp-json\/wp\/v2\/posts\/710\/revisions\/1986"}],"wp:attachment":[{"href":"https:\/\/presta.site\/blog\/wp-json\/wp\/v2\/media?parent=710"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/presta.site\/blog\/wp-json\/wp\/v2\/categories?post=710"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/presta.site\/blog\/wp-json\/wp\/v2\/tags?post=710"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}