PrestaShop Tips
56 answersPractical PrestaShop know-how from running real shops: performance tuning, clearing the cache the right way, hosting and PHP choices, HTTPS and backups, child themes, hooks, and how edge caching like Cloudflare fits in.
It's for merchants and developers who want their store to stay fast, stable and maintainable, and who'd rather follow tested advice than trial and error. You'll find straight answers on what matters, what to skip, and the mistakes that cost the most time.
Browse the questions below, or read our longer PrestaShop guides for deeper walkthroughs.
Questions
It depends on where you are today. If you want to upgrade from PrestaShop 8 to 9, or move up from 1.7, the honest answer is: only when there's a reason and only after testing on a copy.
If your store runs well and your modules are compatible, there's no urgency. Staying put is a valid choice. Newer versions do bring real gains: faster page rendering, a modernised admin and an updated technical stack. The catch is that the jump is not a one-click affair. It needs a module-compatibility check, a staging copy of your live store, and a full test of checkout, payments and your key modules before you touch production.
Our rule of thumb: upgrade when you need a feature or fix that only the newer line offers, or when your current version is approaching end of support. Not just to be on the latest number. Whatever you decide, never run the upgrade directly on a live shop.
For the full step-by-step, read our PrestaShop 9 migration guide.
PrestaShop 9 needs PHP 8.1 as the absolute minimum; the supported range runs through the latest 8.x releases, with the newest stable 8.x recommended for fresh installs. Anything older than PHP 8.1 will refuse to install.
If you are coming from an older PrestaShop on PHP 7.x, you will almost always bump PHP at the same time. Before you flip the PHP version on your hosting:
- Check that every installed module declares PHP 8.x compatibility. Older third-party modules using PHP 7-era syntax (curly-brace array access,
each(), implicit nullables) throw fatal errors on PHP 8.1+. - Test your theme. Deprecated Smarty plugins and old
create_function()calls fail on modern PHP. - Raise
memory_limitto at least 512 MB for the back office and upgrade process.
Make sure the usual extensions are present: curl, dom, fileinfo, gd, iconv, intl, json, mbstring, openssl, pdo_mysql, simplexml and zip. Keep allow_url_fopen enabled for payment modules.
For the full path, see our PrestaShop 9 migration guide.
As of the official PrestaShop 9 documentation, PrestaShop 9.0 supports PHP 8.1, 8.2 and 8.3 and recommends 8.4; PrestaShop 9.1 supports PHP 8.1 through 8.4 and recommends 8.5. That means PHP 8.1 is the floor, but the best target depends on the exact 9.x release and the modules you run. For a fresh build, pick the recommended minor for your PrestaShop release instead of installing the minimum just because it boots.
Quick server checks before a migration:
php -v
php -m | egrep 'curl|dom|fileinfo|gd|intl|mbstring|openssl|pdo_mysql|simplexml|zip'
php -i | grep memory_limitDo the switch on staging first, then run the installer or upgrade, open the back office, open product/category/checkout pages, and read the PHP error log. A store can meet the core PHP requirement and still fail because an old payment module, theme override or custom module is not PHP 8-clean.
To clear PrestaShop cache properly, start in the back office: Advanced Parameters > Performance, then click Clear cache. That is enough for most template, translation and configuration changes.

When a change still does not appear, clear the deeper layers in the right order: PrestaShop files first, then OPcache, then any CDN, Varnish or full-page cache in front of the shop.
# Run from the PrestaShop root. This deletes cache contents, not the cache directories themselves.
find var/cache/prod -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
find var/cache/dev -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
# Older PS 1.6-style installs may also use these Smarty paths:
find cache/smarty/compile -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
find cache/smarty/cache -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
# Reset web OPcache by reloading the PHP service:
sudo systemctl reload php8.2-fpm
# Apache/mod_php alternative:
sudo systemctl reload apache2Do not rely on a CLI-only opcache_reset() command unless you know CLI and web PHP share the same OPcache pool. On normal PHP-FPM hosting, reloading PHP-FPM is the reliable reset. After a server-level clear, make sure the web-server user can write the cache directories again; wrong ownership after a root-level cleanup is a common cause of new 500 errors.
The common mistake is clearing only the back-office cache and assuming OPcache or a reverse proxy followed. They do not. If you want cache warming and CDN purge automation instead of doing this by hand, Performance Revolution includes cache warming and CDN purge logic, and Redis Cache Manager & Monitor helps manage a Redis cache backend.
Short answer: PrestaShop 8 is the safer maintenance generation for existing shops. PrestaShop 9 is the modernization generation: newer Symfony, newer PHP support, a stronger Admin API direction, and a front office moving toward Hummingbird instead of the old Classic-first ecosystem.
| Area | PrestaShop 8 | PrestaShop 9 | Merchant impact |
|---|---|---|---|
| Core framework | Symfony 4.4 generation | Symfony 6.4 generation | Cleaner long-term platform, but old custom code and modules need testing. |
| PHP baseline | Older PHP range, including PHP 8.1 support in the 8.x generation | PHP 8.1 minimum in 9.0, with newer PHP support added in 9.x | Hosting should be checked before upgrade, especially on older managed servers. |
| Theme direction | Classic-compatible ecosystem is still the normal baseline | Hummingbird becomes the default theme for fresh 9.1 installs | Custom themes and child themes need visual testing, not just a module compatibility check. |
| Admin and developer APIs | More legacy-compatible behavior remains | More Symfony controllers, stricter code paths, Admin API evolution | Custom back office modules, overrides and integrations deserve a staging test. |
| Upgrade risk | Usually lower for live 1.7/8 stores | Higher for stores with older themes, overrides or unmaintained modules | Do not upgrade a production shop before testing checkout, payments, shipping and order emails. |
Should you choose PrestaShop 8 or 9?
Use PrestaShop 8 when the shop is already live, heavily customized, or depends on older modules that have not been checked for PrestaShop 9. Use PrestaShop 9 for new builds, staged rebuilds, and shops where your theme, checkout, payment modules and integrations are already confirmed compatible.
The practical upgrade question is not “is PrestaShop 9 better?” It is “is this exact store ready for the architectural jump?” Check your theme overrides, payment modules, carrier modules, checkout flow, cron jobs, ERP/API integrations and custom hooks before moving.
Useful next steps: read our PrestaShop 9 migration guide, check the module compatibility layer, review child theme compatibility, and see what changed in PrestaShop 9.1 with Hummingbird and multi-carrier work.
For most stores, the best web hosting for PrestaShop is a server that meets the platform's requirements comfortably, PHP 8.1+, MySQL 5.7+ (or MariaDB equivalent), and at least 256MB PHP memory, on SSD storage rather than the cheapest oversold shared plan.
- Small to medium stores: decent shared or managed hosting with the specs above is fine.
- Larger stores (thousands of products, steady traffic): a VPS or dedicated server where you control PHP-FPM, OPcache and Redis pays off, because you can size memory and workers to your catalog.
Avoid ultra-cheap hosts that oversell CPU and RAM. That is the most common cause of slow back offices and timeouts. The exact host depends on your region and budget; tell us your setup and we are happy to advise. Once you have the server, you can squeeze more out of it with Redis and OPcache caching through Performance Revolution.
For the full requirements and tuning, read our PrestaShop hosting guide.
There are two separate numbers here and confusing them is the most common mistake.
PHP memory_limit (per request). This is what PrestaShop actually consumes per page load or admin action. The official PrestaShop 9 documentation recommends at least 512 MB. PrestaShop 8 was happy with 256 MB; the bump in PS 9 reflects the heavier Symfony stack in the back office. Import/export, module installs, mass product updates and the migration assistant all need this higher ceiling. Set it lower and you will get blank screens or "Allowed memory size exhausted" fatals.
Server (host) RAM. This is total memory on the VPS or dedicated box, shared between PHP-FPM workers, MySQL/MariaDB, web server, Redis or Memcached, cron jobs and the OS. Practical baselines:
- Under 1 000 SKUs, light traffic: 2 GB is the realistic floor.
- Mid catalog (1 000 to 20 000 SKUs), caching enabled: 4 GB is comfortable.
- Large catalog (50 000+ SKUs) or multistore: 8 GB+ and a dedicated MariaDB tuning pass.
- Bulk imports, image regeneration, big migration jobs: add headroom or move heavy tasks to CLI cron.
If the shop feels slow, RAM is rarely the first thing to fix. Start with full-page cache, Redis, OPcache and a smaller theme. See our PrestaShop performance tuning guide for the actual order of operations.
A useful capacity check is not simply memory_limit x max_children, because not every worker reaches the limit at once, but the formula tells you whether the host is impossible on paper:
PHP-FPM workers x realistic worker memory + MariaDB buffer pool + Redis/OPcache + OS headroomFor example, ten busy PHP workers with a 512 MB ceiling need more than a 2 GB VPS once MariaDB is included, even if most requests use less than the ceiling. Keep CLI limits high for image regeneration and imports, but avoid letting too many PHP-FPM workers run on a small server. If the Linux OOM killer starts killing PHP or MariaDB, lowering worker count and fixing cache/database pressure is usually better than only raising memory_limit.
Yes, for the right use case. PrestaShop is a strong fit if you want full control over your store, self-hosted and open-source, with no recurring platform fees on your sales. It is widely used across Europe (especially France, Spain, Poland and Italy) and has a large ecosystem of modules and developers.
It is not the right choice if you want zero technical involvement. In that case a hosted platform like Shopify is simpler. PrestaShop expects either some technical knowledge or a reliable developer. The trade-off is ownership: you control the data, the code, and the costs. If you go this route, keeping the store fast and clean matters. That is exactly what our Performance Revolution module is built for.
Back up two things, every time: your files and your database. Miss either one and you cannot restore the store.
- Files, your whole PrestaShop directory, including modules, themes, uploads and configuration. Copy it via FTP, SSH, or your hosting panel's file manager.
- Database, export the MySQL database with phpMyAdmin, the command line (
mysqldump), or your hosting panel.
Do both on a regular schedule, and always right before installing or updating a module. For production stores, an automated backup keeps you covered without having to remember.
Step-by-step: our PrestaShop backup guide.
Performance Revolution lets Cloudflare cache your full HTML pages for anonymous visitors: once a page has been filled into the edge cache, repeat hits on it can be served straight from Cloudflare. Cache misses, the first request, expired entries, and any logged-in or cart traffic. Still reach your origin, so this is an edge layer in front of PHP, not a guarantee that requests never touch it. It is server-side only, no JavaScript tricks.
What it actually does on each request:
- For an anonymous visitor on a cacheable page (home, category, product, CMS, search and similar), it sends the headers that tell Cloudflare to cache the HTML for the TTL you set.
- Logged-in visitors and anyone with a cart get bypass headers, so personalised pages always come fresh from your origin.
- It strips
Set-Cookiefrom anonymous responses, because a CDN will refuse to cache a page that sets a cookie. - It attaches Cache-Tag / Surrogate-Key headers, so when you edit a product or category it can purge just the affected pages instead of the whole site.
Purging adapts to your Cloudflare plan automatically: Business and Enterprise zones purge straight by tag in one call, while free and Pro zones (which only support purge-by-URL) have the tags resolved to exact URLs and cleared in Cloudflare's 30-URL batches. There is also a zone-status check that reads your Cloudflare settings, Rocket Loader, Brotli, HTTP/3, Always Online, SSL mode, browser cache TTL, and flags anything misconfigured.
Two honest limits. First, you must supply a Cloudflare zone ID and API token for API purging to work; without them the module still emits cache headers but can't actively purge. Second, edge caching is off by default and applies to anonymous traffic only, that's deliberate, so you never serve one customer's cart to another.
There is no single official product limit in PrestaShop, and the platform does not stop you at any fixed catalog size. In practice, capacity is decided by your data and your infrastructure rather than by the product count alone.
- Combinations and data volume: a catalog with many attributes, combinations and features multiplies rows far beyond the number of products, and that volume is what the database actually has to carry.
- Database and search work: layered navigation, sorting and the search index grow with the catalog; slow queries and reindexing are usually the first bottleneck.
- Imports and exports: large feeds need scheduled, batched imports; a full-catalog import is a heavier operation than day-to-day browsing.
- Hosting and resources: CPU, memory, disk speed and database configuration set the ceiling; a large catalog on undersized hosting will feel slow regardless of the software.
- Caching, theme and modules: effective caching hides most of the catalog-size effect, while a heavy theme or a poorly written module can undo it.
The honest answer for your store comes from measurement: load-test a staging copy with your real catalog and traffic pattern before committing. For concrete tuning steps, see our PrestaShop performance guide.
Yes. Blog Revolution ships with a native comment system and registers the three PrestaShop GDPR hooks, so you can let readers discuss your articles without bolting on a third-party service or worrying about data-subject requests.

On the comment side you get:
- Comments from logged-in customers or guests (name + email), submitted over an AJAX endpoint so the page does not reload.
- Threaded replies, star ratings, and a moderation queue, approve, reject or mark as spam, or switch on auto-approval if you trust your audience.
- Optional Google reCAPTCHA and reply-notification emails, all toggled from the back office.
On the privacy side, when you enable the GDPR option the module answers PrestaShop's built-in data hooks: it declares what comment data it stores (name, email, IP), exports a customer's comments on a data-access request, and deletes their comments on an erasure request, recalculating affected post ratings afterwards.
One honest note: these hooks cover the comment data this module holds. They are not a store-wide privacy tool and not legal advice. Your overall GDPR posture still needs a policy and, ideally, a DPO.
The native path stores comment status as pending, approved, spam or rejected, and moderation actions recalculate the post rating when ratings are enabled. New comments are checked for the comments-enabled flag, honeypot, consent, length and optional reCAPTCHA before being saved. Auto-approval is off by default, which is the safer setting for a public blog; enable it only if you are comfortable cleaning up spam after the fact.
Blog Revolution can also switch the visible provider to native, Disqus, Facebook or tabbed/social combinations. The GDPR hooks described above cover the module's own native comment records, including guest name/email and IP where stored. They do not export or delete data held by Disqus, Facebook or another external provider, so those services still need their own privacy review and policy wording.
To enable SSL in PrestaShop, install a certificate on your server first (most hosts offer free Let's Encrypt certificates), then in Shop Parameters → General switch on Enable SSL and Enable SSL on all pages, and clear the cache.
A few things that trip people up:
- Mixed-content warnings mean some resources still load over HTTP, check your theme and modules for hardcoded
http://URLs. - Don't touch
PS_SHOP_DOMAINorPS_SHOP_DOMAIN_SSLunless you know exactly why. Getting them wrong can lock you out of the back office.
Once HTTPS is live, you can harden it. MPR Security Revolution can add an HSTS header (Strict-Transport-Security) so browsers refuse to fall back to HTTP, and an upgrade-insecure-requests policy to help mop up mixed content. It does not enable SSL for you, that's the PrestaShop setting above, it secures the connection after it's on.
HSTS has a sharp edge: the module only sends Strict-Transport-Security when the request is HTTPS, and browsers will remember it for the configured max age. Start without includeSubDomains or preload until every subdomain, CDN hostname and legacy redirect is confirmed on HTTPS. The module's default security-header config leaves HSTS and CSP off until you enable them, with CSP report-only available for testing before enforcement.
To verify the change, check both schemes from outside the server:
curl -I https://example.com
curl -I http://example.comThe HTTPS response should show the expected security headers, and the HTTP response should redirect cleanly to HTTPS. If mixed content remains, fix hardcoded asset URLs at the theme/module level; security headers can help, but they are not a replacement for correcting broken resource URLs.
Yes. When you turn on the front-office profiler in MPR Performance Revolution, you decide who can see it: leave the panel off entirely, or show it but restrict it to logged-in employees so customers never see your timings.

One of the most useful PrestaShop performance tips is to profile the live store, not a clean test copy, real traffic, real modules, real data. The profiler adds a small bar that shows each page's SQL query count and time, and lists the slowest queries and slowest module hooks, so you can see exactly where a page spends its time before you change anything.
The common mistake is leaving a profiler visible to the public: it leaks internal details and adds overhead on every request. Keep it employees-only, switch it off once you've found the bottleneck, and act on what it shows, usually a heavy module hook or an unindexed query. The module also handles Redis object caching, asset deferral and OPcache/Smarty cache warming, so the fixes live in the same place as the diagnosis.
The relevant settings are two switches: profiler_panel_enabled turns on the front-office panel, and profiler_employees_only keeps it behind an active back-office employee session. The employee-only setting defaults to on, while the panel itself defaults to off. When profiling starts, the module initializes instrumentation early in the request and then injects the panel before </body> only if the collector is enabled and the employee gate passes.
For deeper SQL and hook attribution, the module includes optional overrides that record every database query and per-module hook timing, and the query profiler logs slow queries over the configured threshold, which defaults to 0.1 seconds. Install those only when you need that level of visibility, because they deliberately add instrumentation overhead. A good workflow is: enable employees-only profiler, reproduce one slow URL, capture query/hook totals, disable it, then make the smallest cache, index or module change that addresses the measured bottleneck.
A child theme inherits from a parent theme so you can change templates and CSS without ever touching the parent's files, when the parent updates, your work stays intact. On current PrestaShop versions the recipe is the same:
- Create a new folder in
/themes/(for examplemy-child/). - Add
config/theme.ymlwith aparent:line pointing at the parent (classicorhummingbird) anduse_parent_assets: trueso the parent's styling still loads. - Put your overrides in
assets/css/custom.cssandassets/js/custom.js, and copy only the templates you want to change, using{extends file='parent:...'}so you override single blocks instead of whole files. - Activate it under Design > Theme & Logo.
Common mistake: editing the parent theme directly, then losing everything on the next update. If you'd rather not hand-build the scaffolding, our free Child Theme Generator outputs a ready-to-install ZIP (Classic, Hummingbird or Warehouse) with the theme.yml, asset files and example overrides already wired up. For the full walkthrough, read our PrestaShop child themes guide.
Yes, treat it as a priority. PHP 7.4 reached end of life in November 2022, so it no longer gets security fixes; staying on it means running your store on software with known, unpatched holes. Move from PHP 7.4 to a currently supported PHP 8 release, and verify the exact target PHP version against your PrestaShop, theme and module stack. The good news is that a PHP upgrade is usually a server-side switch, not a full store rebuild. Your shop files stay where they are.
Don't flip the version on your live server first, though. The safe order is: copy your store to a staging environment, switch PHP there, then walk the front office and back office looking for errors. Check each module and your theme against the new PHP version before you commit. The things most likely to break are an old theme or an unmaintained module, not the shop core. Once staging is clean, change the PHP version on production via your hosting panel and re-test.
If a module or theme can't run on PHP 8, that's your signal it needs updating or replacing. For planning a larger move alongside the PHP change, see our PrestaShop migration guide.
As of PHP's own support table, PHP 7.4 ended support on 28 November 2022 and current supported branches are PHP 8.x. For PrestaShop specifically, do not jump to an arbitrary PHP version just because the host offers it: PrestaShop 8 and 9 have different compatibility ranges, and individual modules may be stricter than the core.
On staging, check these before production: run a full order, login, registration, password reset, admin product save, module configuration save, image upload and cron/import job. Then scan the PHP log for deprecations that may become fatals on the next upgrade. Keep the old PHP version available until the rollback window closes, because the fastest rollback is often changing the PHP selector back while you replace the incompatible module.
PrestaShop uses MySQL or MariaDB as its database engine. As of the current official PrestaShop 8 and PrestaShop 9 system requirements, both list SQL support as MySQL 5.7 minimum or MariaDB 10.2 minimum, with a recent version recommended.
For a new or upgraded production store, treat those as minimums, not ideal targets. MySQL 8.0 or a current MariaDB LTS release is a better choice than an old MySQL 5.7 host, especially for larger catalogues, search tables, combinations, carts and order history. Use InnoDB tables, keep enough buffer pool memory available, and make sure backups and restore tests are part of the hosting plan.
PrestaShop 9 also has higher platform expectations than older installations; the official requirements recommend more PHP memory per script than PrestaShop 8. Database compatibility alone is not enough: PHP version, extensions, memory limit, filesystem permissions and module compatibility still need to be checked before upgrading.
If you are on shared hosting, ask the host for the exact MySQL/MariaDB version and whether you can enable the slow query log or get slow query reports. That matters more in day-to-day PrestaShop performance than the brand name of the database server.
On new hosting, ask for the exact engine and version, not just "MySQL compatible". Some managed hosts run MariaDB behind a MySQL label, and that is normally fine, but you still need a version that meets PrestaShop's requirement and a configuration that can handle your catalog. For performance, the important knobs are usually InnoDB buffer pool size, disk latency, indexes, slow query visibility and whether the database is competing with PHP on a tiny shared server.
During migration, dump and restore with the correct character set, keep the same table prefix unless you are deliberately changing it, and test search, product save, order creation and back-office grids after import. Old stores can carry MyISAM tables or stale indexes from very old PrestaShop versions; converting to InnoDB and cleaning indexes should be done deliberately with a backup, not as a blind hosting-panel button.
A staging copy is a private duplicate of your live store where you can test modules, updates and changes without touching production. Set one up like this: (1) Copy all files to a separate location, e.g. a subdomain such as staging.example.com. (2) Create a new database and import a dump of your production database. (3) Update /config/parameters.php with the new database credentials. (4) In the database, update the ps_shop_url table and the domain/SSL entries in ps_configuration to match the staging domain. (5) Clear the cache.
Two things people forget: stop the staging copy from sending real customer emails (disable transactional mail or point it at a test mailbox), and add a robots.txt disallow or password so search engines never index the duplicate. That gives you an independent environment to test safely before anything goes live.
For the full walkthrough, see our guide on setting up a PrestaShop staging site.
Generally yes, but uninstall first, do not just delete the folder. Disabling a module only switches it off; its database tables, hooks and config rows stay behind. The right order is:

The normal path is Modules > Module Manager, then search for the module, open its action menu and choose Uninstall. After uninstalling, PrestaShop can remove the module folder, or you can delete the folder from modules/modulename/ once the uninstall completed cleanly.
Some modules intentionally keep historical data after uninstall, especially payment, order, shipping, support, marketplace and audit modules. That is not always a bad uninstall routine: invoices, order references, validation logs or license history may need to stay readable even when the module is disabled.
- Back up your database and files first, so a bad cleanup is reversible.
- In the back office, click Uninstall on the module. This runs the module's own uninstall routine and removes the data it created.
- Then delete the module folder (the back office can do this for you after uninstalling).
Skip the uninstall and delete the folder directly, and you leave orphaned tables and hook records in the database. For white-screen and 500-error recovery, see our PrestaShop troubleshooting guide.
SELECT m.id_module, m.name, h.name AS hook_name
FROM ps_module m
LEFT JOIN ps_hook_module hm ON hm.id_module = m.id_module
LEFT JOIN ps_hook h ON h.id_hook = hm.id_hook
WHERE m.name = 'modulename';
SELECT id_tab, class_name, module, active
FROM ps_tab
WHERE module = 'modulename' OR class_name LIKE '%ModuleName%';There are two cases where you should pause: if the module provided payment, shipping, tax, marketplace or ERP integration, first confirm there are no active orders, carriers, webhooks or cron jobs still depending on it; and if the module is custom, inspect its uninstall routine because some modules intentionally keep historical tables for audit reasons. A good cleanup is to uninstall one module at a time, reload the back office, open the front office, and check the PHP error log before continuing.
Module source usually explains why the back-office uninstall step matters. Well-built modules remove tabs, configuration, hooks and sometimes custom admin preferences in their uninstall() method. Deleting only the folder skips that cleanup and can leave broken menu entries, dead hooks or database tables that make later upgrades harder to debug.
Your PrestaShop admin URL is based on the physical admin directory name on the server. There is normally no separate database or configuration value that tells PrestaShop the back-office URL.

To find it by FTP, open the PrestaShop root directory and look for a folder such as admin123abc, admin-dev, or backoffice. The admin URL is your shop domain plus that folder name, for example https://example.com/admin123abc/.
With SSH, you can list likely admin folders from the shop root:
cd /var/www/html/prestashop
ls -ld admin* backoffice* 2>/dev/null
for d in admin* backoffice*; do test -f $d/index.php && echo $d; doneIf you are unsure whether you are in the correct PrestaShop root, check for files such as config/settings.inc.php, app/config/parameters.php, classes, modules, and themes. Those confirm the shop root, but they do not store the admin folder name.
If no admin-like folder is visible, check whether your host hides system folders, whether you are in the wrong document root, or whether the shop was deployed into a subdirectory.
Two extra checks help on real servers. First, the admin folder may not literally start with admin; some shops rename it to a private word, so look for a directory containing an index.php and controllers rather than relying only on the name. Second, if the store is installed below a subdirectory, include that base path in the URL, for example https://example.com/shop/admin123abc/.
If you find several candidates, check modified dates and open the folder over HTTPS rather than deleting anything. If the browser redirects to the installer or front office, you are probably in the wrong document root or looking at an old copy. When you do regain access, bookmark the exact URL in your password manager; changing the admin folder name later is a filesystem rename plus cache awareness, not a normal back-office setting.
Yes. PrestaShop is a strong choice if you want the best ecommerce platform for multiple stores on one server, and you have two ways to do it. You can use PrestaShop's built-in multistore (one installation running several shops) or run completely separate installations in different directories or subdomains.
Multistore is the convenient route when your shops share a catalog, customers or back-office team, you manage everything from one admin and reuse products across stores. The trade-off is more configuration complexity and shops that share one codebase and database. Separate installations are simpler to reason about and fully isolated (one shop can't affect another), but each needs its own updates, backups and maintenance.
The right answer comes down to one question: do your stores share products and customers? If yes, lean toward multistore; if they're really independent brands, separate installs are cleaner. See our PrestaShop hosting guide for the server side.
PrestaShop overrides let you change core behaviour without editing core files: you place a copy of a class or controller in the /override folder and PrestaShop loads yours instead. The catch is that only one override per class can win, if two modules override the same class, the second one silently loses, and that is the most common cause of module conflicts in PrestaShop.
This is why modern modules lean on hooks and Symfony services instead, which can stack safely. When you are choosing a module, prefer one that does its job through hooks rather than overrides. It is far less likely to clash with what you already have installed.
More detail: hooks vs overrides in PrestaShop.
In Design → Image Settings, set sensible dimensions for each image type so you are not serving huge files where a thumbnail would do. Compress images before you upload them with a tool like TinyPNG, ShortPixel or Squoosh, and enable compression at the server or via a CDN with image optimisation. Use WebP where your setup supports it, it produces noticeably smaller files than JPEG at similar quality. Deferring off-screen images with lazy loading helps too. For the full picture, see our PrestaShop performance guide.
Yes, but treat it as a structured migration, not a one-click copy. Export products, categories, customers, addresses, orders, images, URLs, and SEO metadata from Shopify or WooCommerce, map them to PrestaShop fields, import in batches, then verify prices, taxes, stock, carriers, payment modules, and redirects. Orders and passwords often need special handling because platforms store them differently.

Use a staged checklist: first migrate catalogue data and images, then customers and addresses, then historical orders, then SEO URLs and redirects. Passwords usually cannot be copied as working passwords because Shopify, WooCommerce and PrestaShop hash them differently, so plan a password-reset campaign unless you have a verified compatible migration module.
Before launch, run a final delta for new customers, orders, stock and prices created since the staging migration. Then crawl old Shopify handles or WooCommerce slugs, test the 301 redirect map, and compare order counts, customer counts, tax totals and stock totals before changing DNS. The broader server-side launch checklist is in the PrestaShop migration guide.
Plan the data model before importing. Shopify variants and WooCommerce variations need to become PrestaShop combinations with the right attributes, references, prices, images, stock, and default combination. Categories, manufacturers or brands, features, specific prices, tax rules, customer groups, order statuses, payment names, carrier names, CMS pages, blog content, and meta titles/descriptions should be mapped explicitly instead of relying only on column names.
Password migration is usually the hardest customer-data issue because hashes are platform-specific; many migrations import customer accounts and then require a password reset. Order history can often be imported for reference, but refunds, payment transactions, invoices, and shipping events may not map perfectly to PrestaShop's native lifecycle. Before launch, run a staging migration, crawl old URLs, build a redirect map from Shopify handles or WooCommerce slugs to PrestaShop URLs, freeze changes during the final delta, and reconcile totals, taxes, stock, and order counts.
You can find the PrestaShop version in the Back Office footer, in Advanced Parameters > Information, and in the codebase via app/AppKernel.php or config/settings.inc.php depending on version. In modules, _PS_VERSION_ is the runtime constant used for compatibility checks.

grep -R "_PS_VERSION_" config/settings.inc.php app/AppKernel.php 2>/dev/null
php -r 'require "config/config.inc.php"; echo _PS_VERSION_, PHP_EOL;'For day-to-day admin work, the back-office footer and Advanced Parameters > Information are the safest places because they show the version of the running shop. For code checks, newer PrestaShop versions commonly expose the version through AppKernel, while older installations may define it in config/settings.inc.php. A module's own version number is not the PrestaShop version; it only identifies that module release.
For PrestaShop 1.6, the filesystem check is usually config/settings.inc.php, where _PS_VERSION_ is defined. For PrestaShop 1.7 and 8, app/AppKernel.php commonly exposes the application version used by the running shop. On any generation, the back-office footer and Advanced Parameters > Information are better than guessing from a copied file because they reflect the installed shop that actually booted.
If you maintain several shops, also check the admin URL you are logged into before reading the footer: a staging shop, production shop and restored backup can have different versions even when they share similar files or database names.
If you are checking compatibility before installing or upgrading a module, use the running shop version and compare it with the module's declared compatibility range. In custom module code, use version_compare(_PS_VERSION_, 'x.y.z', '>=') style checks instead of hard-coding assumptions from a file path. After a major upgrade, clear cache and confirm the back office reports the expected version, because stale files or an incomplete deployment can make filesystem checks misleading.
The short version: PrestaShop hooks are the supported, shared way to extend the shop, and overrides are a heavier fallback for when no hook exists. A hook is a named point in the code (and in templates) where PrestaShop invites modules to add content or behaviour. Many modules can attach to the same hook at once, so two modules adding to the product page don't collide. That's why hooks are the first choice.
An override replaces a core class or controller with your own copy. It's more invasive: only one override can take effect per overridden class, so two modules that both override the same class will conflict, and your override can stop matching core after an update. Reach for an override only when there is genuinely no hook for what you need, and keep the changed code minimal so it's easy to re-check later.
For the full hook list, how to add your own, and override patterns that survive updates, see our PrestaShop hooks and overrides guide.
A PrestaShop migration to a new domain is mostly a matter of updating where the shop thinks it lives, then redirecting the old address. The short version: (1) Copy all files to the new server or location. (2) Update the ps_shop_url table in the database with the new domain. (3) Update PS_SHOP_DOMAIN and PS_SHOP_DOMAIN_SSL in ps_configuration. (4) Update /config/parameters.php if the database credentials changed. (5) Clear all caches. (6) Set up 301 redirects from every old URL to its new equivalent. (7) Update Google Search Console, Google Analytics and any ad accounts with the new domain.
Don't skip the 301 redirects, they pass the link equity you've already earned to the new domain and stop customers hitting dead pages. Add the new domain as a fresh property in Search Console and submit your sitemap so Google re-crawls quickly.
For the full walkthrough and common pitfalls, see our PrestaShop troubleshooting guide.
A PrestaShop migration, new server, new domain, or a changed URL structure, only puts your search visibility at risk if old URLs stop resolving. The fix is to make every old URL either stay the same or 301-redirect to its new home, so the link equity you've built transfers across instead of being lost.
The short version:
- Map every URL first. Crawl your current site and pull your top pages from Search Console, then list each old URL and the new URL it should point to.
- Use 301 (permanent) redirects, never 302. A 301 passes link equity to the new URL; a 302 doesn't.
- Keep HTTPS and the www/non-www choice consistent so you don't create accidental duplicate or 404 URLs.
- Regenerate your XML sitemap with the new URLs and resubmit it in Search Console; use the Change of Address tool if the domain changes.
- Watch Search Console for crawl errors and indexing changes in the first weeks, and fix any broken redirect immediately.
Redirects and sitemaps preserve the value you've earned, they don't manufacture new rankings. For the full step-by-step process, follow our PrestaShop migration guide.
In SEO Revolution, large migration maps can be handled in the Redirects area instead of hard-coding every rule in .htaccess. Redirect rows store the source URL, target URL or target entity, redirect type, active flag, hit count and last-hit date. The module supports 301, 302 and 410, so moved pages, temporary moves and permanently removed pages can be treated differently.
The redirect manager has useful migration safeguards: exact URL matches are checked first, path-only matches can preserve the original query string, and prefix redirects preserve the unmatched child path unless doing so would hijack a real module route. When adding redirects, the code can collapse chains so old URL → intermediate URL → final URL becomes old URL → final URL where appropriate.
The sitemap side should be checked after redirects are in place. The sitemap verifier skips non-200 URLs, redirected URLs, noindex headers/meta tags and canonical mismatches, while 500-level URLs remain pending for retry. That prevents a newly generated XML sitemap from publishing URLs that Google should not index.
When you migrate a PrestaShop store, URLs often change. Without redirects, every old address returns a 404 to visitors and search engines. A 301 redirect says the page moved permanently and is the right choice for a permanent migration. A 302 is temporary and should not be used for old-to-new URL migration maps.

Prepare an old-to-new map
Export old URLs and new URLs into a two-column file before launch. Keep paths normalized: one host, one protocol, one trailing-slash style, and no redirect chains. For example:
old_path,new_url
/old-product.html,https://www.example.com/new-product
/old-category/,https://www.example.com/new-category/
/3-shoes,https://www.example.com/shoesApache (.htaccess)
Place rules before PrestaShop's own dispatcher rules, above the # Dispatcher block and after RewriteEngine On. If PrestaShop handles the request first, your redirect may never run.
RewriteEngine On
# Exact old-to-new page mapping
Redirect 301 /old-product.html https://www.example.com/new-product
Redirect 301 /old-category/ https://www.example.com/new-category/
# Pattern redirect
RewriteRule ^old-brand/(.*)$ /brand/$1 [R=301,L]
# Strip ID-prefixed category URLs, e.g. /3-shoes -> /shoes
RewriteRule ^([0-9]+)-(.+)$ /$2 [R=301,L]Nginx
For a handful of redirects, use exact locations. For a large migration map, use map in the http context and a single return rule in the server block.
# http {} context
map $request_uri $redirect_target {
default 0;
/old-product.html /new-product;
/old-category/ /new-category/;
/3-shoes /shoes;
}
# server {} context
if ($redirect_target) {
return 301 https://www.example.com$redirect_target;
}For thousands of URLs, generate rules from the CSV or use a redirect module that lets staff manage mappings in the back office. Test before going live with curl -I https://www.example.com/old-product.html; you want 301 Moved Permanently and the final Location. Use curl -IL to spot chains.
Common pitfalls
- Redirect chains: point old URLs straight to the final destination.
- Infinite loops: check www/non-www, HTTP/HTTPS and conflicting module rules.
- Case sensitivity: Linux paths are case-sensitive; use
[NC]in Apache rewrite rules only when you intentionally want case-insensitive matching. - Deleted query strings: keep them only when they carry useful state; strip tracking parameters.
- Short retention: keep important migration redirects for at least a year, often longer for high-value pages.
For the full move, including files, database, theme and redirects, follow our PrestaShop migration guide.
Why theme quality matters more than appearance
Choosing a PrestaShop theme is one of the most consequential decisions you make. A theme controls not just how your store looks, but how it performs, how accessible it is, how well search engines can crawl it, and how easily you can extend it with modules. A poorly built theme creates problems that compound: what looks like a small annoyance at setup becomes a performance bottleneck under load, a maintenance headache during updates, and a worse experience for your customers.
Theme marketplaces are full of themes that look great in demo screenshots but pay little attention to coding standards, performance, or compatibility. This guide helps you look past the surface and spot the red flags that separate a well-built theme from one that will cost you later.
Excessive HTTP requests
One reliable sign of a poorly built theme is an excessive number of HTTP requests. Every CSS file, script, image, font, and external resource is a separate request, and each adds latency, especially on mobile. A clean theme should load a typical product or category page with a modest number of requests; poorly built ones routinely double or triple that by loading many separate CSS files, unused JavaScript libraries, fonts from multiple providers, and tracking pixels baked into the theme instead of loaded through modules.
Check it before buying: open the demo in Chrome, open DevTools (F12), go to the Network tab and reload. Look at the request count and what's loading, dozens of individual CSS files, multiple copies of jQuery, or requests to unknown third-party domains are red flags. Pay special attention to render-blocking resources in the document head: a good theme defers non-critical CSS and JavaScript so the page starts painting quickly.
Inline styles and hardcoded design
Professional themes use CSS classes and stylesheets, maintainable, overridable and cacheable. Poorly built ones scatter inline styles through their Smarty templates, like style="color:#333;font-size:14px" on individual elements. Inline styles can't be cached separately, are painful to override (everything needs !important), and make customization nearly impossible without editing templates, so your changes vanish on the next theme update. Worse still is design hardcoded in PHP (colours, sizes, dimensions): any change then means editing code.
To check, right-click elements in the demo and Inspect. If most styling appears under element.style rather than from CSS classes, the theme leans on inline styling. Some inline styles are normal (dynamic background images); a majority being inline is the red flag.
Missing or poor responsive design
Most e-commerce traffic is mobile, and Google uses mobile-first indexing, so a theme that works badly on phones hurts the experience where it matters most. But "has a mobile view" isn't enough. Red flags include text overflowing its container, tap targets that are too small, horizontal scrolling, images that don't resize, menus that are hard to use on touch, and checkout forms that are unusable on a phone.
Test the demo on a real phone, not just a resized browser window, resizing doesn't replicate touch, real networks, or mobile rendering. Run the whole purchase flow: browse, open a product, add to cart, check out. Also confirm the theme serves responsive images via srcset or <picture> rather than shipping one huge desktop image to every device.
Hardcoded text without translations
PrestaShop's translation system lets every user-facing string be translated. A properly built theme runs every label, message and heading through it, the Smarty form looks like {l s='Add to cart' d='Shop.Theme.Actions'}, which exposes the string in the back-office translator. Poorly built themes hardcode plain text like <button>Add to cart</button>, which can't be translated, useless for multilingual stores and limiting even for single-language ones.
To check, note specific strings in the demo and look for the theme's translation catalogues or consistent use of translation domains. If the documentation never mentions translations or multilingual support, treat it as a concern.
jQuery conflicts and JavaScript problems
Many Classic and legacy PrestaShop themes load jQuery; a good theme works with the version already loaded, while a poor one bundles its own jQuery (creating conflicts), loads libraries that duplicate functionality, or uses techniques incompatible with other modules. Check whether the target theme loads duplicate or incompatible JavaScript libraries. Conflicts show up as modules failing silently (buttons that don't respond, forms that don't submit, AJAX that doesn't work), console errors, and features that work in the demo but break once you add real modules.
To check, open the demo console (F12, Console) and type jQuery.fn.jquery to see the loaded version, then look in the Network tab for more than one jQuery file. Multiple jQuery copies are a strong red flag. Also watch for console errors while navigating the demo, errors in a controlled demo with only default modules mean far worse in a real store.
Missing hook support
PrestaShop's hook system is how modules integrate with your store, predefined points in the templates (displayHeader, displayTop, displayFooter, displayProductAdditionalInfo and many more) where modules insert content. A good theme supports all standard hooks. A poor one drops hooks to simplify its layout, swaps standard hooks for proprietary ones, or places them where they break the layout. Missing hooks mean installed modules have nowhere to render: a payment confirmation that never appears, a product add-on that's invisible. You then either hand-edit templates (which breaks on updates) or are locked into theme-specific modules.
Check the documentation for a list of supported hooks; if there's no list, that's itself a concern. If you can see template files, search for {hook h='displayHome'} and other standard names.
No child theme support
Child themes let you customize a theme without modifying its original files. The child inherits everything and holds only your overrides, so your work survives parent updates. A theme that doesn't support them forces all changes into its own files, leaving you to choose between skipping updates or losing your customizations. Check the documentation and the theme.yml file: it should support a parent reference. If the developer never mentions child themes, ask before buying.
When a theme does support child themes, you don't have to build the scaffolding by hand, our free Child Theme Generator outputs a ready-to-install ZIP (Classic, Hummingbird or Warehouse) with the theme.yml, asset files and example {extends file='parent:...'} overrides already set up.
Poor accessibility
Accessibility means people with disabilities can use your store, screen-reader users, keyboard-only users, people with low vision or colour blindness. In many regions e-commerce sites are legally required to meet WCAG 2.1 Level AA. Common failures: images without alt text, form fields without labels, insufficient colour contrast, elements that can't be reached by keyboard, removed focus indicators, and misused or absent ARIA attributes.
Do a quick check: navigate the demo with the keyboard alone (Tab, Enter). If you can't reach everything or there's no visible focus indicator, it fails the basics. Run the page through a free tool like WAVE or the Lighthouse Accessibility audit in Chrome DevTools. A well-built theme should score well there.
Bloated file sizes
A theme's weight directly affects load time. Bloated themes ship unnecessary assets, unoptimized images, unminified CSS/JS, and whole libraries used for a single feature, for example several megabytes of CSS when a fraction is used, multiple icon fonts loaded in full for a handful of icons, or libraries like Moment.js included entirely for one function.
Check total transfer size in the Network tab when loading the demo (excluding product images, which vary). A well-optimized theme keeps a typical page lean; a demo loading several megabytes of CSS, JS and fonts is bloated. Watch CSS especially. A framework-based theme should ship only the components it uses. Also confirm production CSS/JS is minified: if you view the source and it's readable, formatted code with comments, there's no proper build process.
How to evaluate a theme before buying
Read theme.yml
The theme.yml file is the configuration heart of a theme. It declares compatibility, registered hooks and their modules, layout definitions per page type (product, category, CMS, checkout) and asset management. If it's minimal or missing key sections, the theme wasn't built to PrestaShop's theme guidelines.
Test with debug mode
If you can install the theme on a test environment, enable PrestaShop's debug mode (_PS_MODE_DEV_ set to true in config/defines.inc.php). It surfaces PHP errors, warnings and notices hidden in production. A good theme generates zero errors and minimal warnings; a flood of them signals code-quality problems.
Check the developer's track record
Research the developer: how many themes they've published, how recently they were updated, and what reviews say. A detailed changelog of fixes and compatibility updates indicates active maintenance; an absent one suggests the theme may be abandoned after the sale.
Verify compatibility
Make sure the theme explicitly states it has been tested with your exact PrestaShop version. "Compatible with recent versions" is too vague, and if the listed compatibility predates the version's release, treat the claim as unverified.
The real cost of a bad theme
A badly built theme has concrete costs: it slows your store and worsens the customer experience, missing hooks force paid developer work for every new module, poor accessibility creates legal exposure, no child-theme support turns every update into a manual merge, and jQuery conflicts quietly break add-to-cart buttons and payment forms. Think in terms of total cost of ownership. A cheap theme that needs constant developer time is far more expensive than a pricier one that works correctly from day one.
Summary checklist
Before you buy: open the demo and check the Network tab for excessive requests; inspect for inline styles that belong in CSS; test the full purchase flow on a real phone; look for hardcoded, untranslatable text; check the console for errors and multiple jQuery versions; verify standard hooks are present; confirm child-theme support is documented; run a Lighthouse accessibility audit and test keyboard navigation; review CSS/JS/font transfer sizes; read theme.yml for proper structure; and check the developer's update history and support responsiveness. Passing every check doesn't guarantee perfection, but it clears the bar that separates professional work from amateur. The time spent evaluating up front saves far more than dealing with a bad theme already running your store.
Related reading: PrestaShop child themes guide and How to Choose the Right PrestaShop Theme for Your Business.
The Hidden Cost of Font Bloat in PrestaShop Themes
Open your browser's DevTools, switch to the Network tab, filter by "Font," and reload your PrestaShop store. If you see more than three or four font files downloading, you have a problem that is silently costing you customers. Most PrestaShop themes ship with a staggering number of font resources that the average store never uses, and every single one of them delays the moment your visitors can actually read your content.
Font bloat is one of the most overlooked performance issues in PrestaShop. Store owners spend hours optimizing images, enabling CCC (Combine, Compress, Cache), and tweaking server configurations, yet they ignore the fact that their theme is loading 800KB or more of font files on every single page load. This article explains exactly why this happens, how to audit your font loading, and what to do about it.
How PrestaShop Themes Bundle Fonts
PrestaShop themes are distributed as self-contained packages. When a theme developer builds a theme, they want it to work out of the box for as many stores as possible. This means they include every font variant and icon library they might conceivably need. The result is a theme that ships with far more font resources than any single store will ever use.
A typical PrestaShop theme includes three categories of fonts. First, there are display fonts used for headings, body text, and UI elements. These are usually Google Fonts like Roboto, Open Sans, Lato, or Montserrat. Second, there are icon fonts like FontAwesome, Material Icons, or theme-specific icon sets. Third, there are fallback or decorative fonts that the theme uses for specific components like banners, badges, or promotional sections.
The problem compounds because each font family typically ships in multiple weights and styles. A single font like Roboto might include Regular (400), Medium (500), Bold (700), and their italic variants, each as a separate WOFF2 file. Multiply that across two or three font families plus an icon library, and you quickly reach 12 to 15 individual font files loading on every page.
The FontAwesome Problem
FontAwesome deserves its own section because it is the single biggest font-related performance offender in PrestaShop themes. The full FontAwesome 5 library weighs approximately 150KB for the webfont file alone, plus another 60-80KB for its CSS. FontAwesome 6 is even larger. The library contains over 1,600 icons, but the average PrestaShop store uses maybe 20 to 30 of them.
That means you are forcing every visitor to download over 200KB of font and CSS data just so you can display a shopping cart icon, a search magnifying glass, and a few social media logos. This is an absurd trade-off, and it happens because theme developers find it easier to include the entire library than to subset it for each store's specific needs.
The Classic theme ships with FontAwesome, which still contains hundreds of icons you will never use. The newer Hummingbird theme moved away from FontAwesome in favor of SVG icons, which is a significant improvement, but many third-party themes and modules still rely on FontAwesome and load their own copy on top of whatever the theme provides.
Google Fonts and the Performance Tax
Google Fonts are the most popular web font service, and PrestaShop themes make heavy use of them. However, loading Google Fonts the default way creates a chain of performance-killing requests.
When your theme loads Google Fonts via the standard link tag, the browser must first connect to fonts.googleapis.com to download the CSS file. That CSS file then tells the browser to download the actual font files from fonts.gstatic.com. Each of these connections requires DNS resolution, TCP handshake, and TLS negotiation. On mobile connections, this chain can add 300-500ms of delay before a single character of text renders on screen.
Even worse, Google Fonts CSS uses the font-display descriptor set to "swap" by default since 2019, but many older themes still reference Google Fonts CSS URLs that predate this change. Without font-display: swap, the browser may hide all text on the page until the font downloads, creating the dreaded Flash of Invisible Text (FOIT) where visitors see a blank page for one to three seconds.
There is also a privacy concern. Loading fonts from Google's CDN means Google receives information about every visitor to your store, including their IP address and the pages they visit. Under GDPR, this requires explicit consent, and a German court ruled in January 2022 that using Google Fonts without consent violates GDPR, resulting in fines.
How to Audit Your Font Loading
Before you can fix the problem, you need to understand exactly what fonts your theme is loading and which ones you actually need. Here is a systematic approach.
Open Chrome DevTools (F12), go to the Network tab, and check the "Disable cache" checkbox. Reload your page and filter by "Font" in the filter bar. You will see every font file the browser downloads. Note the file names, sizes, and the initiator column which tells you which CSS file requested each font.
Next, use the Coverage tab in DevTools (Ctrl+Shift+P, then type "Coverage"). Start a coverage recording and navigate through your store. The Coverage tab shows you exactly how much of each CSS file is actually used. For FontAwesome's CSS, you will typically see 90% or more marked as unused.
You can also use the Lighthouse audit in DevTools. Run a performance audit and look for the "Reduce unused CSS" and "Ensure text remains visible during webfont load" opportunities. Lighthouse will specifically call out font-related performance issues.
For a more thorough analysis, use WebPageTest (webpagetest.org) to run a test from a mobile connection. Look at the waterfall chart and find the font requests. Note when they start loading relative to other resources and how long they take. On a 3G connection, font loading delays become painfully obvious.
Removing Unused Fonts Step by Step
Once you know which fonts your theme loads and which ones you actually need, it is time to remove the excess. The approach differs depending on your theme's architecture.
For themes that load Google Fonts via a link tag in the header template, find the template file that contains the Google Fonts reference. In most themes, this is in templates/layout/head.tpl or a similar file. If you are using a child theme, copy this template to your child theme directory before editing. Remove or modify the Google Fonts link to include only the weights and families you actually use.
For FontAwesome, check whether your theme loads it via a CSS file in the assets/css directory or via a CDN link. If it is a local file, you have two options. You can replace the full FontAwesome package with a subset that contains only the icons you use, or you can replace icon font usage with inline SVGs entirely.
To subset FontAwesome, use a tool like IcoMoon (icomoon.io) or Fontello (fontello.com). These tools let you select only the specific icons you need and generate a custom font file that might be 5-10KB instead of 150KB. You will need to update the CSS class names if the tool generates different ones, but most allow you to keep the original FontAwesome class names.
For Google Fonts, check every CSS file in your theme for @font-face declarations. Theme developers sometimes import fonts directly in CSS rather than through the head template. Use your DevTools search (Ctrl+Shift+F) to search across all loaded resources for "@font-face" and "fonts.googleapis.com."
Implementing font-display: swap
If you keep any web fonts, make absolutely sure they use the font-display: swap descriptor. This tells the browser to immediately show text using a fallback system font while the web font downloads in the background. Once the web font is ready, the browser swaps it in. This eliminates FOIT and ensures your content is readable instantly.
For Google Fonts loaded via CDN, add the display=swap parameter to the URL. For example, change fonts.googleapis.com/css2?family=Roboto:wght@400;700 to fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap. Note that Google added this parameter by default in 2019, but many PrestaShop themes still use older URL formats.
For self-hosted fonts with @font-face declarations in your CSS, add font-display: swap to each @font-face block. Open your theme's CSS file containing the @font-face rules and add the property. It goes inside the @font-face block alongside font-family, src, and font-weight.
Be aware that font-display: swap can cause a Flash of Unstyled Text (FOUT) where text briefly appears in the fallback font before switching to the web font. This is a much better experience than invisible text, but you can minimize the visual jarring by choosing fallback fonts that closely match your web font's metrics. The CSS size-adjust, ascent-override, and descent-override properties help with this.
Self-Hosting Fonts vs CDN Loading
Self-hosting your fonts rather than loading them from Google's CDN offers several significant advantages for PrestaShop stores.
Performance improves because you eliminate the extra DNS lookup and connection to Google's servers. Your fonts load from the same domain as your other assets, which means the browser can reuse existing connections. With HTTP/2 or HTTP/3, all your font files can download simultaneously over a single connection.
Privacy compliance becomes simpler because visitor data no longer gets sent to Google. This eliminates a GDPR concern entirely, and you do not need to add Google Fonts to your cookie consent banner.
Reliability improves because you are not dependent on an external service. If Google's CDN has an issue (rare but it happens), your fonts still load.
To self-host Google Fonts, use the google-webfonts-helper tool (gwfh.mranftl.com/fonts) which provides a simple interface to download any Google Font in WOFF2 format with the correct @font-face CSS. Download only the weights and styles you need, place the files in your theme's assets/fonts directory, and add the @font-face CSS to your theme stylesheet.
The only potential disadvantage of self-hosting is that you lose the possibility of a cache hit if the visitor has already loaded the same font from Google's CDN on another site. However, browsers have largely eliminated this cross-site caching for privacy reasons since 2020, so this advantage no longer exists in practice.
Font Subsetting: The Nuclear Option
Font subsetting means removing characters you do not need from a font file. A typical Latin web font includes characters for dozens of languages, many of which your store does not use. By subsetting to only the characters your store needs, you can reduce font file sizes by 50-70%.
The tool pyftsubset from the fonttools Python library is the most reliable way to subset fonts. You can specify exactly which Unicode ranges to include. For a store that operates only in English, you might subset to Basic Latin (U+0020-007F) plus Latin-1 Supplement (U+00A0-00FF) for currency symbols and accented characters.
For stores operating in multiple languages, you need to be more careful. Include the Unicode ranges for all languages your store supports. Google Fonts CSS actually does this automatically with unicode-range descriptors, loading character subsets on demand, but self-hosted fonts need manual subsetting.
A simpler approach is to use the WOFF2 format exclusively and drop support for older formats. WOFF2 uses Brotli compression and produces files 30% smaller than WOFF. Every modern browser supports WOFF2, so unless you need to support Internet Explorer 11, there is no reason to include WOFF, TTF, or EOT formats. Many PrestaShop themes still ship with all four formats for backward compatibility that is no longer necessary.
System Font Stacks: The Zero-Cost Alternative
The most radical fix for font performance is to not use web fonts at all. Modern operating systems ship with high-quality fonts that look excellent on screen. A system font stack uses whatever font the operating system provides, which means zero font files to download and instant text rendering.
The modern system font stack looks like this: font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif. This gives you San Francisco on Apple devices, Segoe UI on Windows, and Roboto on Android. All of these are clean, modern, highly readable sans-serif fonts.
GitHub, Bootstrap 5, and many high-performance websites use system font stacks. The visual difference between a system font and a Google Font like Open Sans or Roboto is minimal, especially for body text. Most of your customers will not notice or care whether your store uses Roboto loaded from a server or Roboto already installed on their Android phone.
To implement a system font stack in PrestaShop, you need to modify your theme's CSS to replace the existing font-family declarations, remove the @font-face rules and Google Fonts link tags, and delete the font files from your theme's assets directory. If you are using a child theme, you can override the parent theme's font declarations without modifying the parent theme files.
What About Icon Fonts?
If you remove FontAwesome or another icon font, you need an alternative for displaying icons. The best modern approach is inline SVG. SVG icons render crisply at any size, can be styled with CSS, and only add weight for the specific icons you use rather than loading an entire icon library.
PrestaShop's Hummingbird theme uses SVG icons natively, which is one of the reasons it performs better than Classic. If your theme uses FontAwesome, you can replace individual icons with SVGs from sources like Heroicons, Feather Icons, or even FontAwesome's own SVG files (which are available separately from the font version).
For a PrestaShop store, you typically need fewer than 30 unique icons: cart, search, user account, heart/wishlist, arrows, social media logos, and a few category-specific icons. As inline SVGs, these might total 10-15KB, compared to 150-200KB for the full FontAwesome font and CSS.
Measuring the Impact
After removing unused fonts, measure the improvement. Run Lighthouse before and after, comparing the Performance score, First Contentful Paint (FCP), and Largest Contentful Paint (LCP). Font optimization typically improves FCP by 200-500ms on mobile connections.
Check the total transfer size in DevTools Network tab. A well-optimized PrestaShop store should transfer fewer than 50KB of font data total. If you switch to system fonts, that number drops to zero.
Also verify that your store still looks correct. Check every page type: homepage, category, product, cart, and checkout. Some themes use specific fonts for specific elements, and removing a font might cause unexpected fallback rendering. Always test thoroughly before deploying font changes to production.
Summary: A Font Loading Checklist
Audit your current font loading with DevTools Network tab filtered to fonts. Identify which fonts are actually used by checking CSS coverage. Remove any Google Fonts families or weights you do not use. Replace full icon fonts with subsetted versions or inline SVGs. Add font-display: swap to all remaining @font-face declarations. Self-host your fonts instead of loading from Google's CDN. Consider WOFF2-only to eliminate older, larger formats. Evaluate whether system fonts could replace your web fonts entirely. Measure before and after with Lighthouse and WebPageTest. The goal is simple: load only what you need, load it efficiently, and never make your visitors wait for fonts they cannot see.
For a full speed checklist, see our PrestaShop performance guide.
Classic vs Hummingbird, side by side
PrestaShop ships with two official themes: Classic and Hummingbird. Classic is the long-standing default; Hummingbird is the newer, performance-focused alternative. Choosing between them isn't about which looks better. They take fundamentally different approaches to front-end architecture, and your choice affects performance, module compatibility, customization effort, and long-term maintainability. Here's a side-by-side comparison to help you decide whether you're starting fresh or weighing a migration.
Architecture: what changed and why
Classic uses jQuery and Smarty templates with a traditional server-rendered approach: the server generates full HTML pages and the browser renders them. JavaScript handles interactive pieces like the cart, product page and checkout. The CSS is compiled from Sass into a single large stylesheet.
Hummingbird is a ground-up reimagining. It drops jQuery in favour of vanilla JavaScript and a component-based structure, ships a more modular CSS layer, and carries a noticeably smaller asset footprint.
Dropping jQuery is the most consequential change. It removes a render-affecting dependency and a coding style where modules manipulated the DOM without coordination. Hummingbird leans on modern browser APIs (fetch, querySelector, classList, event delegation) instead, so the theme itself is lighter, but modules written against jQuery need updates. Hummingbird's newer CSS framework also uses custom properties (variables) for easier theming and an updated grid, which affects any custom CSS that referenced the older framework's class names.
Performance: what to expect
Performance is the main reason PrestaShop built Hummingbird. On a like-for-like install, Hummingbird's smaller CSS payload and the absence of render-blocking jQuery generally produce faster First Contentful Paint and Largest Contentful Paint, and a clear drop in Total Blocking Time because there's far less JavaScript to parse and execute on the main thread. Cumulative Layout Shift is roughly even between the two when both are configured well, since layout stability depends more on image dimensions and lazy loading than on the framework.
Treat the gap as directional, not guaranteed: third-party modules add their own CSS and JavaScript, which can narrow or widen the difference depending on how well each module is optimised for the theme. Measure your own pages rather than trusting generic numbers.
Module compatibility: the real catch
This is where Hummingbird's advantages come with a caveat. Many modules were built for Classic's architecture: they depend on jQuery, use the older Bootstrap markup, and assume Classic's template structure. On Hummingbird, jQuery-based JavaScript can fail silently, older components may not render correctly, and template overrides written for Classic won't match Hummingbird's reorganised templates.
Severity depends on your stack. Core PrestaShop modules work on both. Well-maintained third-party modules from active developers typically support Hummingbird; older or abandoned modules may only work on Classic. Before committing to Hummingbird, test every module you plan to use on a staging copy. Pay particular attention to AJAX carts, product customization fields, quick views and checkout steps. When a module ships separate template folders for Classic and Hummingbird, that's the clearest sign it supports both.
Smarty vs Twig: future-proofing
PrestaShop has signalled an intent to move the front office from Smarty to Twig over time, and Hummingbird's template structure is organised with that direction in mind, though both themes still use Smarty for front-office templates today. The practical takeaway: heavy customizations built on Classic's structure may face a larger migration effort if and when that transition lands. Don't decide on a future engine change alone, but it's a point in Hummingbird's favour.
Customization approach
Customizing Classic is well-trodden ground: years of tutorials and forum posts, straightforward Sass, and Smarty templates that are easy to read. Hummingbird asks for updated skills, modern CSS, vanilla JavaScript and a utility-first approach, so the learning curve is steeper if your team leans on jQuery.
In return, Hummingbird's CSS custom properties make many changes simpler. Want to change the primary colour across the whole theme? Edit one custom property instead of hunting down Sass variables and recompiling. Its more semantic HTML also makes elements easier to target and improves accessibility.
Child theme support
Both themes support child themes, the recommended way to customize without editing the parent's files, so your changes survive parent updates. You create a child theme directory, point its theme.yml at the parent, and override only the files you need. The mechanism is the same for both; the difference is that a child theme built on Classic can't be reused on Hummingbird, because the underlying templates are structured differently, you rebuild the overrides against Hummingbird's structure.
If you're commissioning a custom theme, starting from Hummingbird as the parent is the better long-term bet: cleaner architecture, less technical debt, and fewer overrides needed for common changes. Either way, you can scaffold a correct child theme in seconds with our free Child Theme Generator, pick Classic or Hummingbird as the parent and it wires up the theme.yml, asset files and example overrides for you.
Migration path: Classic to Hummingbird
If you run Classic and are weighing a switch, here's what's actually involved. Template overrides must be rebuilt, you can't copy Classic overrides into a Hummingbird child theme, because file structure, variable names and block names differ. Custom CSS needs review and likely revision, since framework class names changed and any jQuery-dependent styling will break. Custom JavaScript needs rewriting from jQuery to vanilla JavaScript, usually the most time-consuming part. And every installed module needs compatibility checking. Plan it as a proper development effort with a staging environment, thorough testing and a rollback plan, not a weekend job.
When to choose Classic
Choose Classic when your store depends on older third-party modules that haven't been updated for Hummingbird; when your team is more comfortable with jQuery and you don't have budget for retraining; or when you're on a tight deadline and want the widest selection of compatible themes and modules. If you're already on Classic with extensive customizations and the store performs well, there may be no compelling reason to migrate at all.
When to choose Hummingbird
Choose Hummingbird when you're starting a new store. The performance advantages come for free with no legacy customizations to migrate. Choose it when performance is a priority, especially for a mostly-mobile audience on slower connections. Choose it to keep your store aligned with where PrestaShop is heading, and when you have developers comfortable with modern JavaScript and CSS. It's also the stronger starting point for accessibility, thanks to more semantic HTML, better ARIA support and keyboard navigation.
Third-party themes
Many stores skip both official themes for a marketplace theme. These are almost always based on Classic's architecture, since Classic has the larger installed base. If you're on a third-party theme, the Classic-vs-Hummingbird question is largely academic for your current store, the author already made the call. When evaluating new third-party themes, check which foundation they're built on, and be wary of themes that claim to be "based on Hummingbird" but only borrow its look while keeping jQuery-dependent internals.
Verdict: no wrong answer, but a better one
For new stores, Hummingbird is the clear pick: lighter, more modern and better aligned with PrestaShop's direction, and the module-compatibility gap keeps shrinking as the ecosystem catches up. For existing Classic stores with significant customizations, do the cost-benefit honestly, measure your current performance, estimate the real migration effort, and decide whether the gain justifies it. Sometimes it does; sometimes the right move is to switch at your next redesign.
Whichever you pick, the fundamentals matter equally: trim asset sizes, lazy-load below-the-fold content, optimise images and audit page speed regularly. A well-optimised Classic store will outperform a poorly configured Hummingbird one every time.
Related reading: PrestaShop child themes guide and How to Choose the Right PrestaShop Theme for Your Business.
Your theme is probably slower than you think
Every store owner has an opinion about their theme's speed, but very few have data. "It feels fast" is meaningless when Core Web Vitals are measured down to the millisecond. To understand your theme's real impact, you need a systematic approach that isolates the theme's contribution from server performance, module overhead and network conditions.
This guide walks through a complete measurement methodology. You'll learn to use Lighthouse, WebPageTest, Chrome DevTools and real user monitoring to quantify exactly what your theme costs in loading time, interactivity and visual stability, and, crucially, how to separate the theme from everything else so you can decide what to optimise.
Why theme performance matters
Your theme controls the whole front-end experience: which CSS loads, how much JavaScript runs, how images and fonts are handled, how the layout is built. A heavy theme can add seconds to load time no matter how fast your server is. Core Web Vitals measure exactly the parts of the experience your theme controls: Largest Contentful Paint (how fast the main content appears), Interaction to Next Paint (how fast the page responds), and Cumulative Layout Shift (visual stability). All three are heavily influenced by theme architecture, which is what makes this a customer-experience analysis, not just a technical one.
Setting up your testing environment
Measuring on a live store while customers browse and load fluctuates gives inconsistent results. Minimise the variables. Ideally use a staging copy: same server profile, same modules, same products, same theme config, just no real traffic. If a full staging isn't possible, test during off-peak hours, run each test at least three times, and average the results.
Disable any caching proxy (like a CDN) for testing, or use a staging URL that bypasses it. CDN caching masks your theme's true cost. Document your baseline: PHP version, active modules, CCC settings (Combine, Compress, Cache) and server specs, so you can reproduce results and compare over time.
Lighthouse: your starting point
Lighthouse is built into Chrome DevTools and is the most accessible audit available. It simulates a mobile device on a throttled connection. To run it, open DevTools (F12), go to the Lighthouse tab, choose "Performance" and "Mobile", and click "Analyze page load." The Performance score is a weighted blend of several metrics, but Largest Contentful Paint and Total Blocking Time dominate, so those are the ones most affected by theme quality.
Run the audit on at least four page types: homepage, category, product, and cart/checkout. Each has different DOM complexity and asset needs, and your theme may behave very differently across them. One caveat: Lighthouse runs simulated, so its absolute numbers don't match real-world experience, they're for comparison (before vs after, theme A vs B). For real numbers you need Real User Monitoring, below. Record every result in a spreadsheet (URL, date/time, score, each metric) to build a baseline.
WebPageTest: deep-dive analysis
WebPageTest (webpagetest.org) is free and far more detailed than Lighthouse, running real browsers on real hardware from locations worldwide. Enter your URL, pick a test location near your main audience and a connection profile (for European stores, a Frankfurt or London location with a Cable or 4G profile), and run at least three tests for a median.
The waterfall chart is the most valuable output: every resource, in order, with its download time. It makes render-blocking resources and unnecessary loads obvious. Watch for render-blocking CSS/JS as long bars before any content renders, large fonts downloading before critical content, and third-party requests (analytics, social widgets, chat) that delay your theme's assets. The filmstrip view shows screenshots at intervals so you can see when text and images actually appear and when layout shifts. The content breakdown shows total weight by type (HTML, CSS, JS, images, fonts), useful for spotting a theme carrying excess weight.
Chrome DevTools Performance tab: frame by frame
The Performance tab gives the most granular view, recording a timeline of JavaScript execution, layout, paint and compositing. Open DevTools (F12), go to Performance, enable "Screenshots" and "Web Vitals," set "Slow 3G" network and "4x slowdown" CPU throttling, then record and reload.
Focus on the Main thread lane. Long yellow blocks are JavaScript execution. Anything over 50ms is a "long task" that blocks interaction and raises Total Blocking Time. Click into them to see the call stack; if the long tasks come from your theme's scripts, that's a theme problem. Red blocks indicate layout thrashing, where the browser recalculates layout repeatedly, often from JavaScript that reads layout properties (offsetHeight, getBoundingClientRect) then mutates the DOM in a loop, a common cause of poor INP. The "Bottom-Up" and "Call Tree" tabs let you sort by total or self time to find the heaviest functions.
Network waterfall for theme assets
The Network tab offers another view. Filter by type (CSS, JS, Font, Img) to isolate theme assets. Identify everything loading from your theme's paths (e.g. /themes/your-theme/assets/), note the count and combined size, then do the same for /modules/ paths to separate the module contribution.
Enable "Disable cache" and reload to simulate a first-time visitor; note total transfer size and the DOMContentLoaded and Load times. Reload again without it to see the repeat-visitor (cached) experience, the difference shows how much your theme benefits from caching. Use the "Initiator" column to trace the dependency chain (a CSS file loaded in the head template is render-blocking; an async/defer script is not), and the "Priority" column to see how the browser ranks each resource. Non-critical resources loaded at high priority are an optimisation opportunity.
The with/without-theme comparison
To truly isolate the theme's impact, compare. On staging, run a full set of measurements with your current theme, record everything, then switch to a default PrestaShop theme (Classic or Hummingbird) and measure again. The difference is your theme's incremental impact relative to the default. It's not perfect, the default has none of your customizations, but it gives you a ceiling for how much theme optimization can buy. A more controlled version: progressively disable theme features (custom fonts, then JavaScript effects, then the icon font), measuring after each to see the cost of each feature.
Core Web Vitals: lab vs field
Core Web Vitals are measured on real users through the Chrome User Experience Report (CrUX), not lab tools. Lab measurements (Lighthouse, WebPageTest) use simulated conditions; field measurements (CrUX, RUM) capture actual experiences across devices, networks and locations. Your Lighthouse score might be 75, but if many of your customers are on older phones and slow connections, the field data can tell a very different story.
See your field data in Google Search Console's Core Web Vitals report or in PageSpeed Insights (pagespeed.web.dev), which shows lab and field side by side when traffic allows. The "good" thresholds are LCP under 2.5s, INP under 200ms and CLS under 0.1, evaluated at the 75th percentile of your users, a high bar, because your slowest visitors weigh heavily. Your theme touches all three: LCP via CSS size, fonts and hero images; INP via JavaScript execution and event handlers; CLS via image placeholders, injected content and font loading.
Real user monitoring: the ground truth
Real User Monitoring (RUM) captures performance from your actual visitors, the most accurate measure of real-world impact, reflecting their real devices and networks. Google Analytics 4 captures Core Web Vitals automatically with the gtag.js snippet; view it under Reports, User Experience, or a custom exploration. For more detail, services like SpeedCurve or Datadog, or the free web-vitals JavaScript library, provide granular data. The web-vitals library is handy because you can add it to your theme and send data to any endpoint.
With RUM you can segment by device, browser, country and page type, which often reveals a theme performing well for desktop Chrome but poorly for mobile Safari. Track it over time to correlate changes with theme updates or module installs, if LCP jumps by 500ms, check what changed that day.
Server-side profiling: backend vs frontend
Sometimes poor speed is blamed on the theme when the real cause is server processing time. Before optimising the theme, confirm the server generates HTML quickly. PrestaShop's built-in profiler (Advanced Parameters > Performance > Debug Mode) adds a debug bar showing SQL query count, SQL time, page generation time and memory. Most pages should generate in well under a second on the server; if generation takes seconds, the problem is the server, queries or module hooks. Fixing the theme won't help.
You can also read server response time (Time to First Byte) in the Network tab: click the HTML document request and look at Timing > "Waiting (TTFB)." If TTFB is high but theme assets are fast, focus on the server (PHP OPcache, MySQL caching, Redis/Memcached, PrestaShop object caching). If TTFB is fast but the page is still slow, the theme is the likely bottleneck.
The before/after benchmarking framework
When you change something, prove it helped. Before any change, run five Lighthouse audits per target page and record the median score and metrics, plus three WebPageTest runs for a median. Save the full reports, not just scores. Make the change, then clear all caches (Smarty cache, OPcache, any CDN cache) and wait at least 60 seconds for OPcache to reset if you edited PHP. Re-run the same five Lighthouse and three WebPageTest tests on the same pages and compare medians. A change is meaningful only if it improves consistently across runs; if some improve and some regress, it's within measurement noise.
Be sceptical of small gains. Lighthouse can vary by a few points between identical runs due to throttle variability, so 62 to 65 may be noise while 62 to 75 almost certainly isn't. For the most rigorous comparison, use WebPageTest's visual comparison to get a side-by-side filmstrip.
Common theme performance problems and how to spot them
Measurement surfaces specific issues, each with a signature. Render-blocking CSS shows as high FCP/LCP with a long gap between TTFB and FCP in the waterfall, fix by inlining critical CSS and deferring the rest. Excessive JavaScript shows as high Total Blocking Time and poor INP, confirmed by long tasks in the Performance timeline. Poor font loading shows as invisible text in the filmstrip or a gap between FCP and text appearing. Layout shift from undimensioned images or injected content shows as high CLS. Learn to read these signatures and performance work turns from guessing into engineering: measure, diagnose from data, fix the specific problem, measure again.
Building a monitoring routine
Measurement isn't a one-off. Weekly, run Lighthouse on your four key page types and log results. Monthly, run a full WebPageTest analysis and compare to last month. After every theme update or module install, run a before/after. Review Core Web Vitals in Search Console monthly. Consider automating with Lighthouse CI (audits in your deployment pipeline) or continuous-monitoring services that alert you when performance degrades, so you catch regressions before they reach customers. The goal isn't a perfect score; it's knowing exactly where your time and bytes go on every page load, and making deliberate, data-driven decisions.
When you do apply theme-side fixes, keep them in a child theme so an update can't wipe them, our free Child Theme Generator scaffolds one in seconds. Related reading: PrestaShop child themes guide and Performance Tuning Your PrestaShop Store: From Database Queries to Full Page Cache.
The honest answer to "free or premium theme?" is that a theme's real cost is rarely its sticker price. A free theme that needs hundreds of euros of customization, drags down performance, or lacks features can end up costing more than a premium theme that works correctly from the start.

What free themes actually offer
PrestaShop ships with an official default theme. It is genuinely well built, it follows the platform's coding standards, supports the standard hooks, works with the translation system, and gets updates alongside the core. If you have CSS skills, it is a legitimate starting point. Beyond the official theme, free third-party themes vary wildly: some are limited "taster" versions of premium themes, some are hobby projects, and a few are free because they carry adware, hidden backlinks, or undisclosed tracking. Treat free themes from unknown sources with extra scrutiny.
What premium themes provide
A premium theme typically gives you a polished design with several layouts and colour schemes, a back-office configurator so you can change colours, fonts and layout without touching code, companion modules (mega menu, product-page layouts, sliders), documentation, a defined support period and compatibility updates. The value is less the design than the development time saved: building those pieces from scratch would cost far more.
Code quality, support and updates
The biggest difference is often invisible: code quality. Developers who sell themes as a business have an incentive to write clean, maintainable code, because bad reviews and support tickets cost them money. Free third-party themes carry no such incentive, so quality is uneven. Premium themes bought through a marketplace come with a support window and a contractual obligation to fix issues; free themes come with none, if it breaks, you fix it, pay someone, or move on. Updates follow the same pattern: premium themes get maintained, many free ones are abandoned after release.
Security and nulled themes
A theme controls the HTML, CSS and JavaScript sent to your customers, so a malicious one can inject mining code, steal form data, or open backdoors. Reputable marketplaces review submissions; random download sites do not. Nulled themes, pirated premium themes, are the worst case: the licence check is stripped out and other modifications (backdoors, data harvesting, SEO-spam injection, cryptomining, redirects) are often added, hidden and obfuscated. There is no legitimate reason to use one; if budget is tight, use the official default theme instead.
Performance, customization and where to buy
The official default theme is optimized and supports PrestaShop's CCC asset combining. The best premium themes match it while adding features through lazy loading and conditional asset loading; the worst load everything everywhere. Free third-party themes tend to perform poorly. Always test a theme's own demo with a tool like Google PageSpeed Insights before committing. For customization, the official theme offers little beyond logo and favicon, while premium themes usually include a graphical configurator. Where you buy matters too: the official PrestaShop Addons marketplace offers the most buyer protection and PrestaShop-specific review, general marketplaces offer wider choice with lighter PrestaShop vetting, and independent sellers range from excellent specialists to high-risk unknowns.
The bottom line
Documentation quality is a reliable proxy for overall quality, a developer who documents thoroughly usually codes carefully too. If unsure, start with the official default theme: free, maintained, secure and broadly compatible. Choose a premium theme when you need a polished store quickly with bundled modules and support. Avoid free third-party themes except for throwaway test stores, and never use a nulled theme. Whatever you pick, work in a child theme, document your changes, test updates on staging, and keep backups. For a deeper walkthrough, read how to choose the right PrestaShop theme for your business.
Why Module Bloat Is the Silent Killer of PrestaShop Performance
Every PrestaShop store starts fast. Then you install five modules, ten modules, thirty modules, and suddenly your homepage takes four seconds to load. The culprit is rarely one massive module. Instead, it is dozens of small modules each adding their own CSS file, their own JavaScript file, and their own database queries to every single page load. This cumulative weight is what we call module bloat, and it is the number one reason PrestaShop stores become slow over time.
The problem is that most store owners never audit what their modules actually load. They install a module for product labels, another for social sharing buttons, another for a newsletter popup, another for analytics, and each one silently registers itself on hooks like displayHeader and actionFrontControllerSetMedia. Even if a module only displays content on product pages, it may still load its CSS and JavaScript files on the homepage, category pages, cart page, and checkout. That means your customers are downloading assets they will never use on that particular page.
A proper module audit reveals exactly what each module contributes to your page weight. It tells you which modules are the heaviest offenders, which ones load assets unnecessarily, and which ones you can optimize or remove entirely. This article walks you through the complete process of auditing your PrestaShop modules for performance, using browser DevTools, PrestaShop debug mode, and systematic analysis.
Step 1: Enable PrestaShop Debug Mode and Performance Profiling
Before you open your browser tools, you need to enable PrestaShop's built-in profiling capabilities. PrestaShop has a debug mode that reveals detailed information about hook execution, module loading times, and database queries. To enable it, you need to modify two settings.
First, go to Advanced Parameters, then Performance in your back office. Set Debug Mode to Yes. This enables error reporting and additional logging that helps identify problematic modules. However, the real power comes from the profiling feature.
To enable full profiling, you need to edit the file defines.inc.php located in your PrestaShop config directory. Find the line that defines _PS_DEBUG_PROFILING_ and set it to true. On current PrestaShop versions, this constant controls whether the profiling bar appears at the bottom of every front office page. Once enabled, reload any page on your store and you will see a detailed profiling panel showing execution times for every hook, every module, and every SQL query.
The profiling panel is divided into several sections. The hooks section shows you every hook that was executed on the current page, which modules are attached to each hook, and how long each module took to execute. The SQL section shows every database query, its execution time, and which module or core function triggered it. The modules section gives you a summary of total execution time per module across all hooks.
Pay special attention to the total execution time column. A well-optimized module should contribute less than 10 milliseconds to a page load. If you see a module taking 50, 100, or even 500 milliseconds, that is a serious performance problem that needs investigation.
Step 2: Using Browser DevTools to Map Module Assets
PrestaShop's built-in profiling tells you about server-side performance, but it does not show you the full picture of what happens in the browser. For that, you need your browser's Developer Tools. Open Chrome or Firefox, press F12, and navigate to the Network tab.
Reload your homepage with the Network tab open. You will see every request the browser makes: HTML, CSS files, JavaScript files, images, fonts, and AJAX calls. The goal is to identify which of these requests come from modules.
In PrestaShop, module assets follow a predictable URL pattern. CSS files from modules are typically served from paths like /modules/modulename/views/css/filename.css or /modules/modulename/css/filename.css. JavaScript files follow the same pattern with js instead of css. Use the filter bar in the Network tab to filter by "modules/" and you will instantly see every asset loaded from your installed modules.
For each module asset you find, note the following information: the file name, its size (both transferred and uncompressed), and whether it loads on the current page type. You want to build a spreadsheet or simple list that maps each module to its assets. A typical audit might reveal something like this: module A loads two CSS files totaling 45 KB and one JavaScript file of 120 KB on every page, but it only displays content on product pages. That means category pages, the homepage, and the cart are all loading 165 KB of unnecessary assets.
The Network tab also shows you the waterfall view, which reveals when each asset starts loading and how long it takes. Assets that block rendering (render-blocking CSS and synchronous JavaScript) are particularly damaging because they prevent the browser from displaying any content until they finish loading. Look for module JavaScript files that load in the head without async or defer attributes, as these are the worst offenders for perceived load time.
Step 3: Analyzing the Network Waterfall Per Module
The waterfall view in DevTools deserves its own section because it reveals performance problems that raw file sizes do not. When you look at the waterfall, you want to identify three types of problems.
First, look for render-blocking resources from modules. These appear as bars that start early in the waterfall and delay the first paint event (the vertical green or blue line). In PrestaShop, CSS files added via the displayHeader hook or through addCSS in setMedia are typically render-blocking. If a module adds a large CSS file that is only needed on specific pages, it blocks rendering on every page for no reason.
Second, look for sequential loading chains. Some modules load a JavaScript file that then triggers loading of additional resources: more JavaScript files, CSS files, web fonts, or external API calls. Each link in this chain adds latency. A module that loads jQuery UI, then a jQuery UI theme CSS, then a custom widget script, then the widget's CSS creates a chain of four sequential requests that could take 200 to 400 milliseconds even on a fast connection.
Third, look for external requests. Some modules make calls to external servers for analytics, tracking, font loading, social media widgets, or API data. These requests are particularly dangerous because you have no control over the external server's response time. A social sharing module that calls Facebook, Twitter, and Pinterest APIs on every page load can add 500 milliseconds or more of latency, and if any of those servers is slow or unreachable, it can block your entire page from finishing its load.
To quantify the impact per module, use Chrome DevTools' blocking feature. Right-click on a request from a specific module and choose "Block request domain" or "Block request URL." Then reload the page and compare the load time. This gives you a direct measurement of how much that module's assets contribute to your total page load time. Repeat this for each module to build a ranking of heaviest to lightest.
Step 4: Hook Execution Analysis
Understanding which hooks each module uses is critical for identifying unnecessary loading. PrestaShop's hook system is the mechanism by which modules inject their content, assets, and logic into pages. The most performance-relevant hooks for front office pages are displayHeader, actionFrontControllerSetMedia, displayTop, displayHome, displayFooter, displayProductAdditionalInfo, and displayProductListFunctionalButtons.
The displayHeader hook is the most commonly abused hook in the PrestaShop ecosystem. Modules register on this hook to add their CSS and JavaScript to the page head. The problem is that displayHeader fires on every single front office page. If a module registers on displayHeader without checking which page the customer is currently viewing, it loads its assets everywhere.
To see which modules are registered on each hook, go to Design, then Positions in your back office. This page shows every hook and every module attached to it. Look specifically at displayHeader and actionFrontControllerSetMedia. Count how many modules are registered there. In a typical store with 30 or more modules installed, you might find 15 to 20 modules on displayHeader alone. Each one is adding at least one CSS or JavaScript file to every page.
Now cross-reference this with your DevTools findings. For each module on displayHeader, check whether that module actually needs to load on the current page. A product reviews module only needs its assets on product pages. A wishlist module only needs its assets on product and account pages. A size chart module only needs its assets on product pages. Yet all of them are loading on your homepage, your category pages, your CMS pages, and your checkout.
The profiling data from Step 1 adds another dimension to this analysis. Some modules not only load unnecessary assets but also execute expensive PHP code on every hook call. A module that runs database queries in its hookDisplayHeader method to check configuration values or fetch data is wasting server resources on every page, even when its output is not needed.
Step 5: Identifying the Heaviest Modules
With data from profiling, DevTools, and hook analysis, you can now rank your modules by their performance impact. Create a list with the following columns: module name, number of CSS files loaded, total CSS size, number of JavaScript files loaded, total JavaScript size, server execution time from profiling, number of database queries, and pages where the module actually displays content.
The modules that score highest across these metrics are your heaviest offenders. In our experience auditing hundreds of PrestaShop stores, the following categories of modules are consistently the worst performers.
Page builder modules are often the heaviest. They load large CSS frameworks, multiple JavaScript libraries for their visual editor, and sometimes even load editor assets on the front office. A page builder that loads 300 KB of CSS and 500 KB of JavaScript on every page is not unusual.
Social media modules that embed widgets from Facebook, Instagram, or Twitter load external scripts that are both large and unpredictable in their loading time. A single Instagram feed widget can add 1 MB or more of JavaScript to your page.
Analytics and tracking modules that use multiple tracking pixels load scripts from external domains. Each tracking pixel typically adds 20 to 50 KB of JavaScript plus additional network requests for pixel images and API calls.
Slider and carousel modules load large JavaScript libraries like Slick, Owl Carousel, or Swiper along with their CSS. Even if the slider only appears on the homepage, the assets often load on every page.
Live chat modules load substantial JavaScript bundles for the chat widget interface, typically 100 to 300 KB, plus they establish WebSocket connections that consume resources throughout the browsing session.
Step 6: Measuring Performance Before and After
Before you start disabling hooks or removing modules, establish a baseline measurement. Use multiple tools to get a comprehensive picture.
In Chrome DevTools, go to the Lighthouse tab and run a performance audit. Record the Performance Score, First Contentful Paint (FCP), Largest Contentful Paint (LCP), Total Blocking Time (TBT), and Cumulative Layout Shift (CLS). Run the audit three times and average the results to account for variability.
Use the Performance tab in DevTools to record a page load trace. This gives you a flame chart showing exactly what the browser is doing at every millisecond. Look for long tasks (blocks longer than 50 milliseconds) and identify which module scripts cause them.
Also measure your page weight. In the Network tab, look at the total number of requests and total transferred size at the bottom of the panel. Filter by CSS and JS separately to get module-specific totals.
Record all these numbers before making any changes. Then, as you optimize modules by unhooking them from unnecessary hooks or disabling them entirely, re-run the same measurements. The difference tells you exactly how much performance you gained from each change.
A well-executed module audit typically reduces page weight by 30 to 50 percent and improves load times by one to two seconds. On stores with many poorly optimized modules, the improvement can be even more dramatic.
Step 7: Disabling Unnecessary Hooks
Once you have identified which modules load assets on pages where they are not needed, you have several options for optimization. The simplest approach is unhooking modules from hooks where they do not need to be.
Go to Design, then Positions in your back office. Find the module on the hook you want to remove it from. Click the trash icon or the unhook button to remove the module from that specific hook. This prevents the module from executing on that hook entirely.
However, be careful with this approach. Some modules use displayHeader not only to load CSS and JavaScript but also to perform essential initialization tasks. Unhooking such a module from displayHeader might break its functionality on pages where it is actually needed. Always test on a staging environment or at minimum test the specific pages where the module should still work after unhooking.
A better long-term approach is to contact the module developer and request conditional asset loading. A well-coded module should check the current controller or page type before loading its assets. For example, a product reviews module should only load its CSS and JavaScript when the current controller is ProductController. This way, the module stays hooked to displayHeader for compatibility but only loads assets when they are actually needed.
If you are comfortable editing module code, you can add conditional checks yourself. In the module's hookDisplayHeader or hookActionFrontControllerSetMedia method, add a check for the current controller name. If the controller is not one where the module displays content, return early without adding any assets. This is the most targeted and effective optimization you can make.
Practical Checklist for Your Module Audit
To summarize the entire audit process, here is a practical checklist you can follow. Start by enabling PrestaShop debug profiling. Open DevTools Network tab and reload your homepage. Filter requests by modules path and list every module asset. Note the size and type of each asset. Check Design, then Positions for modules on displayHeader. Cross-reference hook registrations with where modules actually display content. Use DevTools request blocking to measure per-module impact. Record baseline Lighthouse scores. Unhook modules from hooks where they are not needed. Add conditional loading to modules that load globally. Re-measure Lighthouse scores after each change. Document your findings and changes for future reference.
This systematic approach ensures you do not miss any performance opportunities and gives you concrete data to justify every change you make. Module bloat is not a mystery. It is a measurable, solvable problem, and every PrestaShop store benefits from a thorough module audit at least once a year.
For more performance guides, see our blog.
If you have ever inspected your store's source and wondered why a module that only shows a widget on product pages is also loading its CSS and JavaScript on the homepage, category pages and even checkout, you are not alone. It is one of the most common performance problems in PrestaShop, and it comes from how the hook system works combined with shortcuts taken during development.
Why it happens
PrestaShop lets modules add assets through hooks such as displayHeader and actionFrontControllerSetMedia. Both fire on every front-office page. There is no built-in mechanism that limits a hook to specific page types. It is entirely up to the module to check which page is being viewed and decide whether to add its assets. Many modules skip that check and simply register their CSS and JavaScript on every call, so the module always works regardless of where its content appears. It also means those files load everywhere, whether they are needed or not.
The newer actionFrontControllerSetMedia hook (with registerStylesheet and registerJavascript) gives better control over priority and placement, but it fires on every page too. The registration method changes; the loading scope does not. Without a conditional check, the assets still load globally.
What good modules do
A well-built module checks the current controller before loading anything. Every front-office page is served by a specific controller, for example the homepage, category, product or cart controllers. Inside the hook the module reads $this->context->controller and only registers its assets when the page actually uses them. A product-reviews module, for instance, should load its assets on product pages and nowhere else. This is a handful of lines of code, yet plenty of modules skip it.
How to find the offenders
- Open Chrome DevTools on your homepage, go to the Network tab, reload and filter requests by
/modules/. Count the requests and their combined size. On a page where most modules show nothing, that is pure overhead. - Compare with a product page, where many modules legitimately need their assets. On a tidy store the product page loads more module assets than the homepage; if the numbers are nearly identical, modules are loading everything everywhere.
- Enable PrestaShop's debug profiling to see which modules execute on each hook. Any module that runs on
displayHeaderoractionFrontControllerSetMediabut produces no visible output on the current page is a candidate. - Sort assets by size and start with the biggest files, a large global JavaScript file matters far more than a tiny CSS one.
How to fix it
First, ask the developer. Most professional developers will add conditional loading when you send specific data: which method loads the assets, which pages actually need them, and the measured size and impact. If the module is yours to edit, add the controller check yourself. When you cannot modify the module (encrypted code, or you do not want to maintain a fork), a small custom module can unregister the global assets and re-add them only on the pages that need them, or your theme configuration can remove specific module assets. Always re-test every page where the module should still work. Removing its CSS can break the look and removing its JavaScript can break interactions.
The best prevention is to evaluate a module before installing: check its demo with DevTools, look at the hook methods if the code is available, and read reviews for performance complaints. For a deeper walkthrough, see our PrestaShop performance guide.
Get a few settings right and Cloudflare gives your PrestaShop store a faster CDN, DDoS filtering and a WAF in front of your origin. Get them wrong and you get redirect loops, broken checkouts and phantom orders, so this is the short, safe checklist.
- SSL/TLS mode: Full (Strict). Never use Flexible, it sends HTTP to your origin and causes infinite HTTPS redirect loops in PrestaShop. Install a Cloudflare Origin Certificate if you don't have one.
- Disable Rocket Loader. It defers and reorders PrestaShop's inline JavaScript, which breaks add-to-cart, payment forms and the back office.
- Never cache dynamic pages. Bypass cache for the cart, checkout, customer account and admin directory; only cache static assets. "Cache Everything" without bypass rules can serve one customer another's cart.
- Restore real visitor IPs with
mod_remoteip(Apache) orngx_http_realip_module(Nginx), readingCF-Connecting-IP, otherwise every order logs a Cloudflare IP. - Keep mail DNS unproxied (grey cloud) and don't let Bot Fight Mode block payment webhooks.
Cloudflare handles the edge; your origin still has to be fast. For server-side caching and asset optimisation inside PrestaShop, see Performance Revolution.
If you use Performance Revolution's CDN page cache with Cloudflare, treat it as a controlled HTML cache, not a blanket "cache everything" rule. It is off by default and only marks anonymous, front-office GET/HEAD HTML pages as eligible. Logged-in customers, carts with products, session cookies, AJAX, admin/API requests, dynamic query strings and explicit bypass signals are sent with bypass/no-store headers.
Eligible anonymous HTML receives CDN-oriented headers such as Cloudflare-CDN-Cache-Control with max-age plus stale-while-revalidate and stale-if-error values. The default CDN TTL settings in the module are 2592000 seconds for max age, 86400 seconds for stale-while-revalidate and 604800 seconds for stale-if-error, but they only matter after you enable the CDN cache feature and deploy current rules.
curl -I https://example.com/category-page
Check: X-MPR-Cache: eligible or bypass
Check: Cloudflare-CDN-Cache-Control
Check: no Set-Cookie on eligible anonymous HTMLFor purging, the module can send Cloudflare purge requests when the zone ID and API token are configured. Cloudflare Business/Enterprise can purge by tags; on lower plans the module falls back to resolving affected URLs and purging them in batches.
WebP is a modern image format that compresses product photos to noticeably smaller files than JPEG or PNG at similar visual quality, so your pages download less and render faster, useful on image-heavy catalogs.
Enable it in PrestaShop:
- Go to Design → Image Settings (Preferences → Images on older builds) and find the image generation options.
- Choose JPEG/PNG + WebP for fallback safety, or WebP only if you're confident about your audience.
- Set WebP quality around 80–85 for product photography, save, then regenerate thumbnails.
On large catalogs the browser-based regeneration can time out. Run it from the CLI instead so it isn't bound by the web-server timeout.
Common pitfalls:
- No WebP support in PHP: GD or ImageMagick must be built with WebP. Check with
gd_info(); if missing, ask your host. - Server not serving WebP: PrestaShop writes WebP alongside the JPEG/PNG, but the server must negotiate by the browser's
Acceptheader. Make sureimage/webpis a known MIME type. - Stale caches: purge browser, Smarty, OPcache, CDN and any full-page cache after switching, otherwise old image URLs stick.
- Module conflicts: sliders or zoom modules that hardcode
.jpgmay show broken thumbnails; test them.
If you'd rather not wire up regeneration and .htaccess negotiation by hand, Performance Revolution generates WebP (and AVIF) and serves the right format by Accept header automatically. For the wider picture, see our PrestaShop image optimization guide.
Critical CSS is the small slice of styles a browser needs to paint what visitors see first, the above-the-fold area. By default a PrestaShop store loads its full theme and module stylesheets before it can show anything, which is why a heavy CSS payload leaves people staring at a blank page on slower connections. Inlining the critical CSS and deferring the rest lets the page appear right away while the remaining styles load in the background.
How render-blocking CSS slows the first paint
Every <link rel="stylesheet"> in the <head> blocks rendering until it is downloaded and parsed. A typical store combines a theme stylesheet, several module stylesheets and sometimes a CSS framework, which can easily add up to hundreds of kilobytes. The browser cannot paint a single pixel until all of it arrives, which directly hurts First Contentful Paint and Largest Contentful Paint in Core Web Vitals.
How to defer CSS in PrestaShop
- Extract the critical CSS for each main page type (home, category, product), the rules needed for the visible area.
- Inline it in the
<head>so the first paint needs no extra request. - Defer the full stylesheet by loading it asynchronously (for example with a preload + onload swap), so it no longer blocks rendering.
- Audit your modules, a module that loads its CSS on every page instead of only where it is used is a common source of wasted render-blocking weight.
Doing this by hand is fiddly and easy to break on each theme update. Performance Revolution generates and serves critical CSS per page type and defers non-critical assets for you, so you get the benefit without maintaining the inlining yourself. For the wider picture, see our PrestaShop performance guide.
Changing your PrestaShop admin URL means renaming the admin folder on your server and updating one config value to match. The admin folder is a real directory in your PrestaShop root (named something like admin1234), and PrestaShop stores that name in its config file. Get those two in sync and your back office answers on the new URL; let them drift apart and you lock yourself out, so do them together.
The safe way to do it
- Connect by FTP or SSH and open your PrestaShop root (the folder with
classes/,modules/andthemes/). - Rename the admin folder to something unguessable but memorable for you, e.g.
store-mgmt-7x9. Avoid obvious names likeadmin,administratororbackend: those are exactly what scanners try first. - Update the config so the stored admin directory name matches the new folder name exactly. This step is the one people forget. A mismatch gives you a white page or a 500 error.
- Clear the cache (empty the
var/cache/folders) so old references to the previous name are gone. - Test the new URL in your browser; you should land on the login page.
Two things to watch: do a real rename, not a symlink to the old folder (the old name would still work and defeat the point), and don't rename while colleagues are logged in. Their sessions break instantly. Afterwards, update bookmarks and password-manager entries, and check any custom .htaccess rules or modules that hardcoded the old path.
Renaming raises the bar against automated brute-force login attempts, but it is one layer, not the whole job. Pair it with a strong password and the steps in our PrestaShop security guide. If you only need to locate (not change) the URL, see how to find your admin panel URL.
PrestaShop is moving its template engine from Smarty to Twig, the engine used across Symfony. The back office has largely made the switch; the front office (themes) still runs on Smarty. Here is what that means for you.
The syntax, side by side
- Files: Smarty
.tpl→ Twig.html.twig - Output:
{$product.name}→{{ product.name }} - Filters:
{$var|default:'N/A'}→{{ var|default('N/A') }} - Conditions/loops:
{if}…{/if},{foreach}…{/foreach}→{% if %}…{% endif %},{% for %}…{% endfor %} - Inheritance:
{extends file='parent.tpl'}→{% extends 'parent.html.twig' %}
Where the migration stands
The transition began with the Symfony-based admin pages and has progressed version by version until the back office is essentially Twig. Smarty stays in the codebase because the front-office themes, many third-party modules, and module admin pages built on legacy AdminControllers still rely on it.
What it means for you
- Store owners: nothing breaks immediately. Before a major upgrade, confirm your modules and theme are compatible and test in staging first.
- Module developers: front-office
.tpltemplates still work; for new admin pages on current versions, render Twig from a Symfony controller, and detect the version at runtime if you support both. - Theme developers: Twig auto-escapes output (better XSS safety) and integrates natively with Symfony forms, routing and translations. Keep templates simple now to ease a later port.
Planning a jump to the latest major version? See our PrestaShop migration guide.
Why Server Migration Requires Planning
Moving a PrestaShop store to a new server is one of the most critical operations you can perform. A poorly planned migration can result in hours or even days of downtime, lost orders, broken images, email delivery failures, and SEO damage from search engines encountering errors on your site. With proper planning, you can reduce downtime to minutes, or even cut over with no visible downtime for your customers.
This guide walks you through the entire process, from pre-migration preparation to post-migration verification.
Pre-Migration Checklist
Before touching anything, complete this checklist -
- Verify new server requirements - Confirm the new server meets PrestaShop's PHP version, MySQL version, required PHP extensions (gd, curl, intl, mbstring, zip, etc.), and has enough disk space and RAM
- Document current configuration - Note your current PHP version, php.ini settings, database credentials, cron jobs, email settings, and any custom server configurations
- List all domains and subdomains - Include the main domain, any multistore domains, and subdomains used for static content or CDN origins
- Identify custom files - Note any files outside the standard PrestaShop structure (custom PHP files, .htaccess rules, etc.)
- Check SSL certificate - Plan for SSL installation on the new server before switching DNS
Phase 1 - Prepare the New Server
Install Required Software
Set up the new server with the same software stack as the old one, or better -
# Example for Ubuntu/Debian
sudo apt update
sudo apt install apache2 mysql-server php8.1 php8.1-mysql \
php8.1-gd php8.1-curl php8.1-intl php8.1-mbstring \
php8.1-zip php8.1-xml php8.1-bcmath
# Enable required Apache modules
sudo a2enmod rewrite ssl headers expiresConfigure PHP Settings
Match or improve the PHP settings from your old server -
# In php.ini
memory_limit = 512M
max_execution_time = 300
max_input_time = 300
post_max_size = 64M
upload_max_filesize = 64M
max_input_vars = 10000Create the Database
# Log into MySQL and create database
mysql -u root -p
CREATE DATABASE prestashop CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER 'ps_user'@'localhost' IDENTIFIED BY 'strong_password_here';
GRANT ALL PRIVILEGES ON prestashop.* TO 'ps_user'@'localhost';
FLUSH PRIVILEGES;Install SSL Certificate
Install Let's Encrypt or your commercial SSL certificate on the new server before migration. You can use the HTTP-01 challenge with a temporary domain or the DNS-01 challenge to get a certificate without pointing your domain to the new server yet.
# Using certbot with DNS challenge
sudo certbot certonly --manual --preferred-challenges dns \
-d yourdomain.com -d www.yourdomain.comPhase 2 - Transfer Files
Create a Complete File Backup on the Old Server
# On the old server, create a compressed archive
cd /var/www/html
tar czf /tmp/prestashop_files_$(date +%Y%m%d).tar.gz prestashop/Transfer Files to the New Server
Use rsync for efficient file transfer - it is faster than FTP and can resume interrupted transfers -
# Transfer files from old server to new server
rsync -avz --progress -e ssh \
/var/www/html/prestashop/ \
user@new-server:/var/www/html/prestashop/Set Correct Permissions
# On the new server
find /var/www/html/prestashop -type d -exec chmod 755 {} \;
find /var/www/html/prestashop -type f -exec chmod 644 {} \;
chown -R www-data:www-data /var/www/html/prestashopPhase 3 - Transfer the Database
Export the Database from the Old Server
# On the old server
mysqldump -u root -p --single-transaction --routines --triggers \
prestashop > /tmp/prestashop_db_$(date +%Y%m%d).sqlTransfer and Import to the New Server
# Transfer the SQL file
scp /tmp/prestashop_db_*.sql user@new-server:/tmp/
# Import on the new server
mysql -u ps_user -p prestashop < /tmp/prestashop_db_*.sqlPhase 4 - Update Configuration
Update Database Connection Settings
Edit app/config/parameters.php on the new server -
'database_host' => '127.0.0.1',
'database_port' => '',
'database_name' => 'prestashop',
'database_user' => 'ps_user',
'database_password' => 'strong_password_here',Do NOT Change Shop URLs Yet
Keep the shop URLs pointing to the same domain. Do not change PS_SHOP_DOMAIN or PS_SHOP_DOMAIN_SSL, the domain stays the same, only the server behind it changes.
Phase 5 - Test on the New Server
Before switching DNS, test the new server by modifying your local hosts file -
# On your computer, edit the hosts file
# Windows: C:\Windows\System32\drivers\etc\hosts
# Mac/Linux: /etc/hosts
# Add this line (use the new server's IP)
203.0.113.50 yourdomain.com www.yourdomain.comNow browse to your domain in a browser. You will see the site running on the new server while everyone else still sees the old server. Test thoroughly -
- Homepage, category pages, product pages
- Add to cart and checkout process
- Admin panel login and navigation
- Image loading (check for broken images)
- Module functionality
- Email sending (if possible)
Phase 6 - The Switchover (Minimizing Downtime)
This is the critical phase. Here is how to minimize downtime -
The Zero-Downtime Approach
- Lower DNS TTL in advance - At least 48 hours before migration, lower your DNS TTL to 300 seconds (5 minutes). This ensures DNS changes propagate quickly.
- Put the old store in maintenance mode - This prevents new orders from being placed on the old server that would be lost.
- Do a final database sync - Export the database again from the old server and import it on the new server to capture any orders or changes since the initial transfer.
- Do a final file sync - Run rsync again to catch any file changes.
- Switch DNS - Update your domain's A record to point to the new server's IP address.
- Take the new store out of maintenance mode - Your store is now live on the new server.
# Final sync commands (run during switchover window)
# 1. Put old store in maintenance mode (in old server's DB)
mysql -u root -p prestashop -e \
"UPDATE ps_configuration SET value='1' WHERE name='PS_SHOP_ENABLE';"
# 2. Final database export from old server
mysqldump -u root -p --single-transaction prestashop > /tmp/final_sync.sql
# 3. Transfer and import to new server
scp /tmp/final_sync.sql user@new-server:/tmp/
mysql -u ps_user -p prestashop < /tmp/final_sync.sql
# 4. Final file sync
rsync -avz --delete -e ssh \
/var/www/html/prestashop/ \
user@new-server:/var/www/html/prestashop/
# 5. Enable store on new server
mysql -u ps_user -p prestashop -e \
"UPDATE ps_configuration SET value='0' WHERE name='PS_SHOP_ENABLE';"Phase 7 - Post-Migration Verification
Clear All Caches
# On the new server
rm -rf /var/www/html/prestashop/var/cache/prod/*
rm -rf /var/www/html/prestashop/var/cache/dev/*Regenerate the .htaccess File
Log into the admin panel on the new server, go to Shop Parameters > Traffic & SEO, and click Save to regenerate the .htaccess file.
Verify SSL
Check that your SSL certificate is working correctly on the new server. Visit your store with https:// and verify the padlock icon appears.
Test Email Delivery
Send a test order or contact form submission to verify that email delivery works from the new server. Update SMTP settings if needed.
Check Cron Jobs
Recreate any cron jobs that existed on the old server (sitemap generation, module-specific crons, etc.).
Monitor for Issues
Keep both servers running for at least 48-72 hours after the switch. Monitor -
- Server error logs for any issues
- Google Search Console for crawl errors
- Order processing to ensure nothing is lost
- Email delivery from the new server
Keep the Old Server as Fallback
Do not cancel the old hosting immediately. Keep it for at least a week in case you need to switch back quickly. If problems arise, you can simply change DNS back to the old server's IP.
Common Migration Pitfalls
Hardcoded Paths in Module Files
Some modules store absolute file paths in the database or configuration files. If the installation path on the new server differs from the old one (e.g., /home/user/public_html vs /var/www/html), these modules may break. Search the database for the old path and update it.
Email Configuration
If the old server used a local SMTP server for sending emails, the new server needs the same configuration. Consider switching to an external SMTP service like Gmail, Amazon SES, or Mailgun to avoid this issue entirely.
Image URLs
Verify that all product images load correctly. PrestaShop stores image file paths relative to the installation directory, but some themes or modules may use absolute URLs. Check the page source for any URLs pointing to the old server.
Mixed Content After SSL
If the new server has a different SSL configuration, you may get mixed content warnings. Ensure all internal URLs use HTTPS by checking the store URL settings and running a mixed content scanner.
Before you start, it pays to confirm the new box is up to spec, see choosing hosting for PrestaShop, and to take a full backup of files and database first.
PrestaShop stores everything, products, orders, customers, settings, in a MySQL database, and the tables use a prefix (default ps_, set at install). Knowing the key tables lets you diagnose faster, run bulk operations the admin can't, and recover when the back office breaks. Here are the ones that matter.

SELECT p.id_product, pl.name, ps.active, ps.price, sa.quantity
FROM ps_product p
JOIN ps_product_lang pl ON pl.id_product = p.id_product AND pl.id_lang = 1
JOIN ps_product_shop ps ON ps.id_product = p.id_product AND ps.id_shop = 1
LEFT JOIN ps_stock_available sa ON sa.id_product = p.id_product AND sa.id_product_attribute = 0
ORDER BY p.id_product DESC
LIMIT 20;
SELECT id_order, reference, id_customer, total_paid, current_state, date_add
FROM ps_orders
ORDER BY id_order DESC
LIMIT 20;Products
- ps_product, one row per product:
id_product,price(tax excluded),reference,active, dates. - ps_product_lang, language-specific name, description, meta and
link_rewrite(the URL slug), one row per product per language per shop. - ps_product_shop, per-shop price, status and visibility (mirrors ps_product on a single store).
- ps_stock_available. The real stock source (not
ps_product.quantity, which is legacy). - ps_product_attribute, combinations/variants; ps_specific_price, discounts and special prices.
Categories
ps_category (nested-set tree: nleft, nright, level_depth), ps_category_lang (names, meta), and ps_category_product (which products sit in which category, with position).
Orders & customers
- ps_orders, one row per order:
reference,id_customer,current_state,total_paid_tax_incl,date_add. - ps_order_detail, line items; ps_order_history, every status change with timestamps; ps_order_state(_lang), status definitions.
- ps_customer (email, hashed
passwd, group), ps_address, ps_cart / ps_cart_product (carts that may never become orders).
Configuration & structure
ps_configuration is the key-value store for every back-office setting; ps_hook_module maps which modules run on which hook and in what order; ps_shop_url maps domains to shops, never edit it by hand.
Optimizing the database
Bulk operations run fastest in SQL, but always back up first, test with SELECT before any UPDATE/DELETE, and never drop module tables (uninstall the module instead). Over time, abandoned carts, old guests, connections and logs bloat these tables; trimming them keeps queries fast. For automated cleanup and caching, see Performance Revolution, and our database performance-tuning guide.
Hooks are PrestaShop's extension points, named places in the code where modules attach to add content or run logic without touching core files. When you need a hook list for PrestaShop, the back office gives you the live one: Design → Positions shows every hook that has a module attached, the modules on it, and the order they run in.
Two kinds of hooks
- Display hooks (prefix
display) inject HTML, e.g.displayHeader,displayTop,displayHome,displayFooter,displayProductAdditionalInfo,displayShoppingCartFooter. - Action hooks (prefix
action) run logic with no HTML, e.g.actionCartSave,actionValidateOrder,actionOrderStatusUpdate,actionProductAdd,actionCustomerAccountAdd.
How execution order is decided
PrestaShop looks up every module registered on a hook in the ps_hook_module table and runs them in position order, lowest first. You can read the exact order with:
SELECT hm.position, m.name AS module_name, h.name AS hook_name
FROM ps_hook_module hm
JOIN ps_module m ON hm.id_module = m.id_module
JOIN ps_hook h ON hm.id_hook = h.id_hook
WHERE h.name = 'displayHeader'
ORDER BY hm.position ASC;For display hooks, position controls visual order; for action hooks, it controls processing order, which matters when modules touch the same data or one depends on another finishing first. New modules are appended to the end; reorder them in Design → Positions (drag and drop) or by editing the position column.
Registering hooks in a module
public function install()
{
return parent::install()
&& $this->registerHook('displayHeader')
&& $this->registerHook('actionCartSave');
}
public function hookDisplayHeader($params)
{
$this->context->controller->addCSS($this->_path . 'views/css/style.css');
}
public function hookActionCartSave($params)
{
$cart = $params['cart'];
$this->logCartActivity($cart);
}Common issues
- Two modules on one display hook producing duplicate output, reorder them or unhook the wrong one.
- CSS/JS load order. A reset must sit at a lower position than the styles that depend on it.
- Performance. Every module on
displayHeaderruns on every page; unhook what you don't need. Count modules per hook:
SELECT h.name, COUNT(*) AS module_count
FROM ps_hook_module hm
JOIN ps_hook h ON hm.id_hook = h.id_hook
GROUP BY h.name
ORDER BY module_count DESC
LIMIT 20;When something looks wrong, enable debug mode, confirm which modules are on the hook and in what order, and test whether reordering or transplanting fixes it before changing code.
See our PrestaShop hooks guide.
Under GDPR, customers in the EEA can ask you to hand over a copy of their personal data (a Subject Access Request) or to delete it (the right to be forgotten), and you have one calendar month to respond. A PrestaShop GDPR module handles the core of this; the rest is process.
Where the data lives
Personal data is spread across your database: ps_customer (name, email, date of birth, IP at registration), ps_address (addresses and phone numbers), ps_orders and ps_order_detail (purchase history), ps_message, ps_connections and ps_guest. Third-party modules add more, newsletters, reviews, wishlists, loyalty. Keep a short inventory of every place that stores customer data so an export is actually complete.
The official PrestaShop GDPR module
PrestaShop's official GDPR module (psgdpr), available in current PrestaShop versions, adds consent checkboxes with timestamps, a customer-facing data export, and an erasure function. GDPR-aware modules can register their data so it's included automatically; modules that don't support that hook must be handled by hand.
Handling access and erasure
Verify identity first (a logged-in account is usually enough; otherwise confirm details only the customer would know, but don't demand excessive documents). For access, export from the module and add the context Article 15 requires: processing purposes, third parties the data was shared with, and retention periods, usually a link to your privacy policy.
For erasure, anonymise rather than delete outright. The module replaces names, emails and addresses with placeholders while keeping the invoice figures (products, prices, taxes) that tax law requires you to retain, commonly 6 to 10 years depending on the country. Don't forget your processors (payment, shipping, email marketing): ask them to delete too, and log every step. Treat self-service erasure requests as requests to review, not instant deletions, in case of open orders.
For the bigger picture see GDPR and cookie compliance for PrestaShop and our privacy policy.
Short answer: for most stores either PrestaShop web server choice is fine, but Nginx tends to use fewer resources under load while Apache is simpler if you depend on .htaccess.
The real difference is architecture. Apache assigns a worker process or thread to each request; Nginx uses an event loop, so a couple of worker processes handle thousands of connections at roughly flat memory cost. That gap barely matters at low traffic but grows as concurrency rises. Which is why busy stores and image-heavy catalogues favour Nginx.
Three practical points decide it for most merchants:
- .htaccess: PrestaShop writes its friendly-URL rules into
.htaccess, which Apache reads automatically. Nginx has no.htaccess, you translate those rules into the server config once, by hand. - PHP-FPM: run PHP through PHP-FPM on either server. It keeps the PHP runtime out of the processes that serve images and CSS, saving memory.
- Static files: Nginx serves the many static requests per page load very cheaply, which is where it pulls ahead on a real storefront.
A common middle path is Nginx in front of Apache: Nginx handles connections and static files, Apache keeps .htaccess support. Nginx tends to use fewer resources under high concurrency and static-file load; Apache is simpler where .htaccess compatibility matters. For deeper tuning, read our PrestaShop performance tuning guide.
How PrestaShop Search Works Internally
PrestaShop includes a built-in product search engine that operates on a full-text index stored directly in the MySQL database. Unlike external search services, this index lives alongside your product data in the same database, which means it is fast to query but requires explicit maintenance to stay current. Understanding how this search system works is the first step to diagnosing and fixing search problems.

When a customer types a query into the search bar on your store, PrestaShop does not scan through every product name and description in real time. Instead, it looks up the query terms in a pre-built index that maps individual words to products. This index is constructed by breaking down product text fields into individual words (tokenization), normalizing them (lowercasing, removing accents), and storing the relationship between each word and the products it appears in, along with a relevance weight.
This approach is fundamentally the same as how search engines like Google work, just on a much smaller scale. The tradeoff is that the index must be rebuilt whenever product data changes in ways that the automatic indexing does not catch, which is the root cause of most search problems in PrestaShop.
The Search Database Tables
PrestaShop's search index is spread across several database tables, each serving a specific purpose in the search pipeline.
SET @id_product = 123;
SELECT COUNT(*) AS indexed_words
FROM ps_search_index
WHERE id_product = @id_product;
SELECT sw.id_word, sw.word, si.weight
FROM ps_search_index si
JOIN ps_search_word sw ON sw.id_word = si.id_word
WHERE si.id_product = @id_product
ORDER BY si.weight DESC
LIMIT 50;ps_search_word
This table stores every unique word that has been extracted from your product data, along with the language it belongs to. Each word gets an id_word that serves as a reference key. The table is language-aware, meaning the word "shoe" in your English catalog and "Schuh" in your German catalog are separate entries, each linked to their respective language ID.
When you look at this table, you will see thousands or tens of thousands of rows depending on the size of your catalog and the number of languages. Every distinct word from every indexed product field is represented here.
ps_search_index
This is the core mapping table. Each row links a product (id_product) to a word (id_word) with a weight value. The weight determines how relevant that word is to that product. A word appearing in the product name carries more weight than the same word appearing in the description, and the weight values are configurable in the back office.
When a customer searches for "blue leather wallet", PrestaShop looks up each word in ps_search_word, finds the corresponding id_word values, then queries ps_search_index for products that match those word IDs. Products are ranked by the sum of their weights for the matching words, with higher total weights appearing first in the results.
ps_search_engine
This table stores referrer search engine patterns used for tracking which search engines send traffic to your store. It is not directly related to the internal search functionality but is often confused with it due to the similar naming.
ps_alias
The alias table stores search term aliases, which are alternative spellings or synonyms that should map to a canonical search term. For example, you might configure "sneakers" as an alias for "trainers" so that customers searching for either term get the same results. Aliases are configured in the back office under Shop Parameters > Search > Search > Aliases.
When and Why Reindexing Is Needed
PrestaShop has an automatic indexing feature that updates the search index whenever a product is saved through the back office. When you edit a product and click Save, PrestaShop re-indexes that specific product, updating its entries in ps_search_word and ps_search_index. This works well for day-to-day product management.
However, automatic indexing does not cover every scenario. There are several common situations where a full reindex is necessary.
Bulk Product Imports
When you import products via CSV, the import process may not trigger the search indexing hooks for every product. This is especially common with large imports where performance optimizations skip non-essential processing steps. After a bulk import, new products may exist in the catalog but be completely invisible to site search.
Direct Database Modifications
If you or a module modifies product data directly in the database (bypassing the PrestaShop object model), the search index will not be updated. This includes SQL updates to product names, descriptions, or other indexed fields. Any database migration, data cleanup, or external synchronization tool that writes directly to ps_product_lang will leave the search index stale.
Language Changes
Adding a new language to your store requires a full reindex because the search index is language-specific. Existing products need their content in the new language to be tokenized and added to the index. Similarly, if you edit product content in a specific language (especially through bulk operations), a reindex ensures the changes are reflected in search.
Search Weight Configuration Changes
When you change the weight values assigned to different product fields (more on this below), the existing index entries retain their old weights. A reindex recalculates all weights using the new configuration.
Module Installations or Updates
Some modules modify product data structures or add searchable fields. After installing or updating such modules, a reindex ensures that any new or modified data is included in the search index.
Corrupted Index
Database crashes, failed migrations, or interrupted indexing operations can leave the search index in an inconsistent state. Symptoms include products that should appear in search results but do not, products appearing for completely wrong search terms, or search returning no results at all. A full reindex rebuilds the index from scratch, resolving these inconsistencies.
How to Reindex Products
Back Office Method
Navigate to Shop Parameters > Search in your PrestaShop back office. At the top of the page, you will find an "Indexing" section with options to rebuild the search index. There are typically two options: add products to the index that have not yet been indexed (incremental), or rebuild the entire index from scratch (full reindex).
For most troubleshooting scenarios, choose the full rebuild. The incremental option only adds missing products and does not update existing entries that may have stale data.
The back office method works well for small to medium catalogs (up to a few thousand products). For larger catalogs, use the indexer cron URL shown in Shop Parameters > Search as an HTTP GET request to avoid browser timeout issues.
Reindexing from the Back Office and Cron URL
The supported rebuild controls are in the Back Office under Shop Parameters > Search, in the indexing section.
Use Add missing products to the index for an incremental pass, or Re-build the entire index when existing indexed data may be stale after imports, direct database changes, language changes or search weight changes.
For automation, use the indexer cron URL shown on that same Back Office page. It points to PrestaShop's search cron controller, for example index.php?controller=searchcron&...&token=...&full=1. The token and full URL are generated by the shop, so copy them from Shop Parameters > Search instead of inventing the URL manually.
Be aware that reindexing locks the search tables briefly during the rebuild. On a busy store, schedule the reindex during low-traffic hours to avoid impacting search availability for active customers.
Weight Configuration: Controlling Search Relevance
PrestaShop allows you to configure how much weight different product fields carry in search results. This is one of the most underused features of the built-in search system.
Available Weight Fields
The weight configuration is found in Shop Parameters > Search. You can assign a weight (typically 1 to 10, though higher values work) to each of these product fields:
Product name: This should typically have the highest weight. When a customer searches for a product by name, the product with that exact name should appear first.
Reference: Product reference codes are often used by B2B customers who know the exact SKU they need. A moderate weight ensures reference-based searches work well without overpowering name-based searches.
Short description: The short description often contains key selling points and product characteristics. A moderate weight is appropriate.
Description: The full description contains the most text and therefore the most potential keyword matches. However, because it contains so much text, a high weight can cause irrelevant matches where a search term appears incidentally in a long description. A lower weight relative to the product name is recommended.
Category: Including category names in search allows customers to find products by category terms even when those terms do not appear in the product's own text.
Brand (manufacturer): Customers often search by brand name. A moderate to high weight ensures brand searches return relevant results.
Tags: Tags are explicitly assigned search terms for products. A high weight for tags gives you direct control over which products appear for specific search queries.
Attributes: Product attribute values (size, color, material) can be included in the search index. This allows searches like "red XL" to return products with those attribute combinations.
Features: Product feature values (weight, dimensions, material type) can also be indexed.
Weight Strategy
A reasonable starting configuration might be: product name at 6, reference at 4, short description at 3, description at 1, category at 2, manufacturer at 3, tags at 4, attributes at 2, features at 2. But the optimal weights depend entirely on your catalog and your customers' search behavior.
If your customers frequently search by SKU or reference number, increase the reference weight. If brand searches are important, increase the manufacturer weight. If you find that long descriptions are causing irrelevant results to rank highly, reduce the description weight or set it to zero to exclude descriptions from the index entirely.
After changing weights, always perform a full reindex for the new values to take effect across all products.
Common Search Problems and Fixes
Products Not Appearing in Search Results
This is the most common search complaint. A product exists in the catalog but searching for it by name returns no results. Causes include: the product was added through an import that did not trigger indexing, the product is disabled or out of stock and the search is configured to exclude such products, or the search index is corrupted.
Fix: First, verify the product is active and visible. Then run a full reindex. If the product still does not appear, check whether the product name contains special characters that might be stripped during tokenization, and check whether the minimum word length setting (in Search configuration) is excluding short words from the product name.
Wrong Products Ranking First
When a search for "blue widget" returns a product called "widget holder" before the actual "blue widget" product, it is usually a weight configuration issue. The product that ranks higher has accumulated more total weight across all indexed fields. Perhaps "widget" appears many times in the description of the holder product, and with a high description weight, those occurrences outweigh a single match in the product name.
Fix: Adjust field weights to prioritize the product name. Set the product name weight significantly higher than the description weight. Reindex after making changes.
Search Returns Too Many Irrelevant Results
This happens when the description weight is too high or when common words appear in many product descriptions. A search for "premium" returns every product whose description contains the word "premium" even when it is not a defining characteristic of those products.
Fix: Reduce the description weight or use the blacklisted words feature to exclude common non-discriminating words from the index. The blacklist is configured in Shop Parameters > Search and allows you to specify words that should be ignored during indexing.
Search Does Not Find Partial Matches
PrestaShop's built-in search does not support true fuzzy matching. If a customer searches for "shoe" they will not find products that only contain the word "shoes" unless the stemming or alias features handle the variation. This is a fundamental limitation of the word-based index approach.
Fix: Use the alias feature to map common variations ("shoe" to "shoes", "TV" to "television"). For more comprehensive partial matching, consider an external search engine like Elasticsearch.
Accented Characters Causing Misses
PrestaShop normalizes accented characters during indexing (for example, converting "cafe" and "café" to the same base form). If this normalization is not working correctly, searches with or without accents may produce different results.
Fix: Verify that the search configuration has accent-stripping enabled. Reindex after verifying. If the problem persists, check the database character set and collation, as mismatched encodings can interfere with text normalization.
Search Performance Optimization
For stores with large catalogs (10,000+ products), search performance can become an issue. The built-in search performs database queries against the index tables on every search request, and with a large index, these queries can become slow.
Database Indexing
Ensure that the ps_search_word and ps_search_index tables have proper database indexes. PrestaShop creates these by default, but if the tables have been altered or rebuilt, indexes may be missing. The key indexes are on id_word and id_lang in ps_search_word, and on id_product and id_word in ps_search_index.
Minimum Word Length
The minimum word length setting controls the shortest word that gets indexed. The default is usually 3 characters, meaning one and two-character words are excluded. Increasing this to 4 reduces the index size and can improve search speed, but it means searches for short terms like "XL" or "TV" will not work. Balance index size against your search requirements.
Blacklisted Words
Adding common words ("the", "and", "for", "with") to the blacklist reduces the index size significantly because these words appear in almost every product description. Smaller index tables mean faster queries.
Table Optimization
After a full reindex, run OPTIMIZE TABLE ps_search_word, ps_search_index in MySQL. The reindex process deletes and reinserts large numbers of rows, which can leave the tables fragmented. Optimization reclaims that space and improves query performance.
Elasticsearch as an Alternative
For stores that have outgrown PrestaShop's built-in search, Elasticsearch provides a significant upgrade in both search quality and performance. Elasticsearch is a dedicated search engine that runs as a separate service and offers features that the built-in MySQL-based search cannot match.
What Elasticsearch Adds
Fuzzy matching allows Elasticsearch to find results even when the search term is misspelled. A search for "leahter" will still find "leather" products. Stemming reduces words to their root form, so "running", "runs", and "ran" all match products containing any of these variations. Synonym support lets you define relationships between words ("sofa" and "couch") at the search engine level rather than through manual aliases.
Faceted search (filtering results by attributes like price range, color, brand) is dramatically faster with Elasticsearch because it is designed for exactly this type of aggregation query. Auto-complete suggestions and "did you mean" features are also native Elasticsearch capabilities.
Performance-wise, Elasticsearch handles large catalogs (100,000+ products) with sub-second response times because it uses inverted indexes optimized for full-text search, unlike MySQL which is primarily designed for relational data.
Integration with PrestaShop
Several PrestaShop modules provide Elasticsearch integration. These modules typically replace the default search controller with one that queries Elasticsearch instead of the MySQL search tables. Product data is synchronized from PrestaShop to Elasticsearch either in real-time (on product save) or via periodic batch synchronization.
Running Elasticsearch requires a dedicated server or container with adequate RAM (minimum 2GB for small catalogs, more for larger ones). It adds operational complexity since you now have another service to monitor and maintain. For many small to medium stores, the built-in search with proper weight configuration and regular reindexing is sufficient.
When to Consider Elasticsearch
Consider Elasticsearch when your catalog exceeds 10,000 products and search performance is degrading, when customers frequently misspell search terms and expect fuzzy matching, when you need advanced features like auto-complete or faceted filtering, or when search quality is a competitive differentiator for your business (B2B stores with complex product catalogs, for example).
The Reindexing Checklist
When search is not working correctly in your PrestaShop store, follow this diagnostic and resolution process. First, verify that the problem products are active, visible, and in stock (if your search excludes out-of-stock products). Second, check the search weight configuration and ensure it matches your priorities. Third, run a full search index rebuild from Shop Parameters > Search or via the indexer cron URL. Fourth, clear the PrestaShop cache after reindexing. Fifth, test the search with specific terms to verify the fix. Sixth, if problems persist, check the ps_search_word and ps_search_index tables directly to verify that the problem products have entries. Seventh, if the index appears correct but search still fails, investigate the search controller logic and any modules that override it.
Regular reindexing, combined with thoughtful weight configuration and a well-maintained alias list, keeps PrestaShop's built-in search working reliably for the majority of stores. For those that need more, Elasticsearch provides an upgrade path without requiring a platform change.
For more diagnostics, see our PrestaShop troubleshooting guide.
PrestaShop OPcache is the PHP bytecode cache: it keeps your compiled PHP in memory so the server skips re-parsing files on every request. It's the layer that matters most for raw response time, and it solves a different problem from PrestaShop's other two caches.
- OPcache (PHP): caches compiled PHP bytecode. Enable it in production and clear it whenever you deploy or update code or modules. Otherwise old code keeps running.
- Smarty cache (templates): caches compiled
.tpltemplates and, optionally, their rendered HTML. Clear it after editing templates, switching themes, or changing module hooks. - Browser cache (client): driven by
Cache-Control/ETagheaders so returning visitors reuse CSS, JS and images without a server round-trip.
The common mistake is clearing the wrong layer: a PHP change that won't appear is OPcache, a template change that won't appear is Smarty, and a stale stylesheet is the browser. MPR Performance Revolution shows live OPcache status (enabled state, scripts cached, hit ratio, memory), clears each layer separately, and re-warms OPcache, Smarty and CCC after a deploy so the first visitor doesn't pay for a cold cache. For the full per-setting walkthrough, see our Performance Optimization guide.
Performance Revolution separates more cache layers than the usual PrestaShop screen: PrestaShop query cache, module cache, Smarty, Symfony cache and OPcache. Its OPcache stats include scripts cached, used/free/total memory, memory percentage, hits, misses and hit ratio when the PHP extension is available and not restricted by hosting.
Clearing is also layer-specific. Smarty clearing calls Smarty's own cache and compiled-template clearing, then also clears the production/development Smarty filesystem directories. OPcache clearing calls opcache_reset(). Symfony clearing targets the environment cache directory while avoiding the Smarty directories, and module cache clearing goes through the module cache manager.
Warm-up is a separate concern from clearing. The module's cache warmer is disabled by default, has a default concurrency of 2 and a default max runtime of 120 seconds, and can warm origin URLs after deployment. CDN edge warming is also separate and only runs when edge warming is enabled.
PHP code changed: clear OPcache.
Theme .tpl changed: clear Smarty.
CSS/JS changed: clear browser/CDN asset cache or change asset version.
After deploy: warm origin/cache so first real visitor does not pay the cold-cache cost.A Content Security Policy (CSP) is an HTTP header that tells the browser which sources may load scripts, styles, images, fonts, frames and connections on your PrestaShop pages. If an attacker injects a script from a source that is not allowed, the browser blocks it. CSP is an extra protection layer; it does not replace fixing vulnerable code.
The directives that matter
default-src 'self'is the fallback.script-srcis the main XSS control and must include only the script sources your theme, modules, analytics and payment flows really need.style-src,img-srcandfont-srcusually need compatibility allowances for PrestaShop themes, fonts and image CDNs.connect-srccovers AJAX, analytics beacons and some payment SDK calls.frame-srcandframe-ancestorsmatter for embedded payment, YouTube, reCAPTCHA and clickjacking protection.object-src 'none'andbase-uri 'self'are safe starter hardening directives.
Starter policy for common PrestaShop stacks
Start in report-only mode and tune from real violations. This example allows common Google analytics/tagging, Google Fonts, images from HTTPS/CDN sources, Google/reCAPTCHA style frames and YouTube embeds. Add payment provider domains such as Stripe, PayPal or your PSP only after testing their full checkout and 3-D Secure flow.
# Apache .htaccess or vhost with mod_headers
<IfModule mod_headers.c>
Header always set Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.googletagmanager.com https://www.google-analytics.com https://www.google.com https://www.gstatic.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https: blob:; font-src 'self' https://fonts.gstatic.com data:; connect-src 'self' https://www.google-analytics.com https://stats.g.doubleclick.net; frame-src 'self' https://www.google.com https://www.youtube.com; frame-ancestors 'self'; object-src 'none'; base-uri 'self'; form-action 'self'"
</IfModule># Nginx server block
add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.googletagmanager.com https://www.google-analytics.com https://www.google.com https://www.gstatic.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https: blob:; font-src 'self' https://fonts.gstatic.com data:; connect-src 'self' https://www.google-analytics.com https://stats.g.doubleclick.net; frame-src 'self' https://www.google.com https://www.youtube.com; frame-ancestors 'self'; object-src 'none'; base-uri 'self'; form-action 'self'" always;Roll it out safely
PrestaShop themes and modules often use inline scripts and styles, so a strict policy can break real store behavior if you enforce it immediately. Run Content-Security-Policy-Report-Only first, test product pages, cart, checkout, account creation, contact forms, payment redirects and 3-D Secure, then switch to the enforcing Content-Security-Policy header once the violation log is clean.
Security Revolution can manage security headers from the back office. Its CSP support is disabled by default for compatibility, starts in report-only mode when enabled, stores CSP violation reports, and can suggest additions from repeated blocked sources. It also covers X-Frame-Options, HSTS, Referrer-Policy and Permissions-Policy. For the wider checklist, see our PrestaShop security hardening guide.
A PHP full-page cache (the kind a "page cache pro" style PrestaShop module provides) and Varnish both serve cached pages, but at different points in the stack, and that's the whole decision.
How a PHP full-page cache works: the request still hits Apache or Nginx, PHP boots and PrestaShop initializes, then the cache module returns a stored HTML copy before the full controller runs. Far faster than rendering from scratch, but PHP still starts on every hit, so there's per-request overhead under heavy load.
How Varnish works: Varnish is an HTTP reverse proxy that sits in front of your web server. On a cache hit it answers straight from memory. PHP never runs and MySQL is never queried. That removes the per-request overhead almost entirely, which is what lets a server absorb large traffic spikes.
When a PHP full-page cache is enough: for most stores, it is. If your server already responds quickly under normal load and you aren't routinely saturating PHP, the extra moving part of Varnish isn't justified. A PHP cache also handles PrestaShop-specific logic (logged-in users, cart contents) inside the application, where Varnish needs cookie rules and cache-variation config.
Reach for Varnish when: you face regular traffic spikes (flash sales, campaigns) that overwhelm PHP, you need very low response times, or you serve a high share of anonymous browsing traffic.
For the PHP full-page cache layer, Performance Revolution serves CDN full-page cache headers for anonymous visitors and manages page-level cache and purges, a sensible step before adding Varnish. For deeper configuration, see our PrestaShop caching guide.
If product thumbnails look stretched, blurry, cropped wrong or simply do not appear, the usual fix is to regenerate the images. PrestaShop keeps a separate resized copy for every image type (small, medium, large, and so on); when those copies are missing or out of date, the storefront shows broken or wrong-sized thumbnails. Regenerating rebuilds every copy from the original.
When you need to rebuild thumbnails
- You added or changed an image type (Design → Image Settings) and existing products still show the old sizes.
- You switched theme and the new theme expects different dimensions.
- Thumbnails are missing or distorted after an import or a server move.
- You enabled WebP and want existing images served in that format.
How to regenerate
For small catalogues, use Design → Image Settings → Regenerate thumbnails in the back office. Large catalogues often hit the PHP time or memory limit there, because each original is loaded into memory and resized one by one. In that case run the regeneration from the command line instead (the Symfony console / a CLI script), which avoids the browser timeout and lets you process the catalogue in batches. Raising memory_limit and max_execution_time beforehand helps too.
A common mistake is keeping huge multi-megapixel originals: they make every regeneration slow and memory-hungry, so resize source images to a sane maximum first. Once thumbnails are healthy, keep new images light and lazy-loaded, see our PrestaShop performance guide for the wider speed picture.
Running PrestaShop on the wrong PHP version causes white screens, broken checkout and module failures, so match your PHP to your PrestaShop branch. Here is the practical mapping.
PrestaShop branch → PHP
| PrestaShop | Minimum PHP | Sensible choice |
|---|---|---|
| 1.6.x | 5.4 | 7.1 |
| 1.7.x | 7.1 | 7.2–7.4 (no PHP 8) |
| 8.x | 7.2 (8.1 branch raised the floor) | 8.1 |
| 9.x | 8.1 | 8.2 or 8.3 |
The big one: no PrestaShop 1.7 release supports PHP 8, Smarty uses functions removed in PHP 8.0, so it crashes. To run modern PHP you need the 8.x or 9.x branch.
PHP end-of-life (php.net schedule)
PHP 7.4 and 8.0 are end-of-life and no longer get security fixes. Running them on a store handling payments is a real risk. Check php.net for the current supported list before you settle on a version.
How to check your PHP version
In the back office, Advanced Parameters → Information shows your active PHP version. Over SSH, php -v shows the CLI version (which can differ from the web value). Don't rely on a temporary phpinfo() file, if you create one, delete it straight after.
Upgrading PHP safely
Test on a staging copy first, check every module and your theme against the new version, then switch PHP in your hosting panel and clear all caches. The things most likely to break are an unmaintained module or an old theme, not the core. Planning a version move at the same time? See our PrestaShop migration guide.
Lazy Loading in 2026: What Browsers Handle Natively vs What Needs a Module
Lazy loading is a performance optimization technique that defers the loading of off-screen resources until the user scrolls near them. In 2026, native browser support for lazy loading has matured significantly, but there are still scenarios where PrestaShop store owners need additional modules or custom implementations. This guide explains exactly what browsers handle on their own, what gaps remain, and how to implement the best lazy loading strategy for your PrestaShop store.
What Native Lazy Loading Covers in 2026
The HTML loading="lazy" attribute is now supported by over 95% of browsers worldwide. This includes Chrome (since v77), Firefox (since v75), Safari (since v15.4), Edge (since v79), and all Chromium-based browsers. This means for most visitors to your store, native lazy loading works out of the box.
How Native Lazy Loading Works
Adding loading="lazy" to an <img> or <iframe> tag tells the browser to defer loading that resource until it is within a certain distance from the viewport. The browser handles all the timing and intersection logic internally, with zero JavaScript overhead.
<!-- Native lazy loading for images -->
<img src="product-image.jpg"
loading="lazy"
width="800"
height="600"
alt="Product Name">
<!-- Native lazy loading for iframes -->
<iframe src="https://www.youtube.com/embed/VIDEO_ID"
loading="lazy"
width="560"
height="315"></iframe>What Browsers Handle Natively
| Feature | Native Support | Notes |
|---|---|---|
Images (<img>) | Yes - all major browsers | Use loading="lazy" attribute |
Iframes (<iframe>) | Yes - all major browsers | Use loading="lazy" attribute |
Responsive images (<picture>) | Yes | Put loading="lazy" on the <img> inside |
| srcset images | Yes | Works with loading="lazy" on the <img> |
| Above-the-fold detection | Partial | Browsers try to detect, but not always accurate |
What Browsers Do NOT Handle
| Feature | Native Support | What to use |
|---|---|---|
| CSS background images | No | IntersectionObserver API or module |
| Video elements | No | Custom JavaScript or module |
| Placeholder/blur-up effects | No | JavaScript library or module |
| Priority hints for above-fold images | Partial | fetchpriority="high" attribute |
| Dynamic/AJAX-loaded content | No | JavaScript-based lazy loading |
| Third-party widget deferral | No | Custom implementation |
Implementing Native Lazy Loading in PrestaShop
For modern PrestaShop themes
Modern PrestaShop themes (such as Hummingbird) often include native lazy loading by default. To verify or add it to your theme, edit your template files where product images are rendered.
For product listing pages, find the template that renders product thumbnails (typically themes/yourtheme/templates/catalog/_partials/miniatures/product.tpl):
{* Before - no lazy loading *}
<img src="{$product.cover.bySize.home_default.url}"
alt="{$product.name}">
{* After - with native lazy loading *}
<img src="{$product.cover.bySize.home_default.url}"
loading="lazy"
width="{$product.cover.bySize.home_default.width}"
height="{$product.cover.bySize.home_default.height}"
alt="{$product.name}">Critical Rule: Never Lazy Load Above-the-Fold Images
The most common lazy loading mistake is applying it to images that are visible without scrolling. This actually hurts performance because the browser delays loading content that the user sees immediately. Google's Core Web Vitals will penalize you for this with a higher LCP (Largest Contentful Paint) score.
Images that should NOT be lazy loaded:
- Your store logo
- Hero/banner images at the top of the page
- The first 1-2 product images on category pages
- Any image visible in the initial viewport without scrolling
For these critical images, use eager loading with priority hints:
<img src="hero-banner.jpg"
loading="eager"
fetchpriority="high"
width="1200"
height="400"
alt="Summer Sale Banner">When You Need a Module: CSS Background Images
PrestaShop themes frequently use CSS background images for sliders, banners, category headers, and promotional blocks. The loading="lazy" attribute does not work for CSS backgrounds. You need JavaScript to handle these.
IntersectionObserver Approach
// Lazy load CSS background images
document.addEventListener('DOMContentLoaded', function() {
const lazyBackgrounds = document.querySelectorAll('[data-bg]');
const observer = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
const el = entry.target;
el.style.backgroundImage = 'url(' + el.dataset.bg + ')';
el.classList.add('bg-loaded');
observer.unobserve(el);
}
});
}, {
rootMargin: '200px 0px'
});
lazyBackgrounds.forEach(function(bg) {
observer.observe(bg);
});
});In your HTML/Smarty template:
{* Instead of inline background-image *}
<div class="category-banner" data-bg="{$category_image_url}"></div>When You Need a Module: Placeholder Effects
Native lazy loading shows nothing until the image loads, which can cause a jarring visual experience. Modules or libraries can add:
- Blur-up effect (LQIP) - Load a tiny, blurred version first, then replace with the full image. Creates a smooth perceived loading experience.
- Skeleton screens - Gray placeholder blocks that match the image dimensions, giving the user a sense of the page layout before images load.
- Dominant color placeholders - Extract the dominant color from the image and use it as the placeholder background. Pinterest popularized this approach.
When You Need a Module: Video Lazy Loading
Product videos and embedded YouTube/Vimeo players should be lazy loaded but cannot use the native attribute (except for iframes). For HTML5 <video> elements:
// Lazy load video elements
const lazyVideos = document.querySelectorAll('video[data-src]');
const videoObserver = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
const video = entry.target;
video.src = video.dataset.src;
video.load();
videoObserver.unobserve(video);
}
});
});
lazyVideos.forEach(function(video) {
videoObserver.observe(video);
});Impact on PrestaShop Performance and Core Web Vitals
Proper lazy loading directly impacts three Core Web Vitals metrics:
- LCP (Largest Contentful Paint) - Lazy loading above-the-fold images HURTS LCP. Only lazy load below-the-fold images.
- CLS (Cumulative Layout Shift) - Images without width/height attributes cause layout shifts when they load. Always specify dimensions.
- INP (Interaction to Next Paint) - Fewer resources loading simultaneously means the main thread is less congested, improving interactivity.
Must-Have: Width and Height Attributes
Without explicit width and height attributes, the browser does not know how much space to reserve for a lazy-loaded image. When the image finally loads, the page layout shifts, causing a high CLS score.
<!-- BAD - causes layout shift -->
<img src="product.jpg" loading="lazy" alt="Product">
<!-- GOOD - reserves space, no layout shift -->
<img src="product.jpg" loading="lazy"
width="400" height="400" alt="Product">
<!-- ALSO GOOD - CSS aspect-ratio -->
<img src="product.jpg" loading="lazy"
style="aspect-ratio: 1/1; width: 100%;" alt="Product">PrestaShop-Specific Lazy Loading Recommendations
Product Listing Pages (Category Pages)
Lazy load all product images except the first row (typically 3-4 products visible above the fold). Use native loading="lazy" for product images and apply fetchpriority="high" to the first row.
Product Detail Pages
The main product image should be loaded eagerly with fetchpriority="high". Thumbnail images in the gallery can be lazy loaded. Related/cross-sell product images at the bottom should be lazy loaded.
Homepage
Slider/carousel images above the fold should be eager loaded (at minimum the first slide). Module blocks below the fold (featured products, new products, etc.) should use lazy loading.
CMS Pages
Images embedded in CMS content are the hardest to optimize because they are typically stored as raw HTML in the database. A module or custom JavaScript is needed to add loading="lazy" to images within CMS content.
Quick Implementation Checklist
- Add
loading="lazy"to all<img>tags below the fold in your theme templates - Add
widthandheightattributes to ALL images (lazy or not) - Use
loading="eager"andfetchpriority="high"on above-the-fold hero images and the first row of products - If your theme uses CSS background images for sliders/banners, implement IntersectionObserver-based lazy loading
- Test with Google PageSpeed Insights to verify LCP and CLS improvements
- Test with real devices on slow connections (Chrome DevTools throttling) to ensure images load before users scroll to them
Summary: Module vs. Native
| Scenario | Approach |
|---|---|
| Standard product images | Native loading="lazy" - no module needed |
| CSS background images | Module or custom JS with IntersectionObserver |
| Blur-up / LQIP placeholders | Module or JS library (lazysizes, lozad) |
| Video lazy loading (HTML5) | Custom JS with IntersectionObserver |
| YouTube/Vimeo embeds | Native loading="lazy" on iframe - no module |
| CMS content images | Module to auto-add loading attribute to stored HTML |
| Third-party widget deferral | Custom JS implementation |
For a deeper dive, read PrestaShop image optimization: alt tags, lazy loading and page speed.
The PrestaShop .htaccess file controls URL rewriting and redirects, and one misplaced rule can take the whole store offline, so edit it carefully and from a backup.

Put custom rules in the right place. PrestaShop regenerates its own rules between two marker comments (# ~~start~~ ... # ~~end~~) whenever you toggle Friendly URLs or click "Generate .htaccess file." Anything you add inside that block gets overwritten, always place your custom redirects before the PrestaShop block.
Use the right redirect type. Use 301 for a page that has permanently moved (it passes link equity), 302 for a temporary move, and 410 for something permanently gone with no replacement.
Don't break the store. The classic mistakes: a catch-all rule that loops forever, or one that swallows the admin, API, modules and static files. Guard against both with conditions, e.g.:
# Add a default language prefix, but never loop or touch admin/api/modules/assets
RewriteCond %{REQUEST_URI} !^/(en|fr|de|es|it|pl)(/|$) [NC]
RewriteCond %{REQUEST_URI} !^/admin [NC]
RewriteCond %{REQUEST_URI} !^/api [NC]
RewriteCond %{REQUEST_URI} !^/modules/ [NC]
RewriteCond %{REQUEST_URI} !\.(css|js|jpe?g|png|gif|svg|webp|ico|woff2?)$ [NC]
RewriteRule ^(.*)$ https://yourstore.com/en/$1 [R=301,L]
Test with a 302 first, verify with curl -I -L, then switch to 301. For lots of redirects or non-technical staff, a database-driven redirect module with a UI is safer than hand-editing. See our PrestaShop troubleshooting guide for recovery if a rule does lock you out.
SEO Revolution's redirect manager is the safer database-driven option for most shop-level URL changes. It supports 301, 302 and 410 redirects, target entity selection for products/categories/CMS and other entities, custom URL targets, active flags, hit counters and last-hit dates. A 410 row has no replacement target and sends a real Gone response.
The module also handles cases that are awkward in .htaccess: exact matches, path-only matches that preserve the original query string, prefix redirects that preserve child paths, and safeguards that prevent a broad prefix from hijacking real module routes. It can also collapse 301 chains when redirects are added or updated, which keeps migration paths cleaner for crawlers.
Use .htaccess for server-wide rules that must run before PrestaShop, such as host, protocol or very early security rewrites. Use the redirect UI for content migrations, retired products, old CMS URLs and day-to-day SEO redirect management where you want reporting and safer edits.
Bots make up a large share of web traffic, and not all of them are friendly crawlers. Scrapers copy product data, credential-stuffing bots hit login forms, fake-account bots abuse registration, and aggressive filter crawlers can pin your server by forcing expensive category pages. A WAF is the best front line, but you can still get useful protection from server limits, application limits and careful allowlists. Test every rule on staging first.
Block obvious bad bots in Apache (.htaccess)
RewriteEngine On
# Block common scraper and attack bots
RewriteCond %{HTTP_USER_AGENT} (SemrushBot|AhrefsBot|MJ12bot|DotBot|BLEXBot) [NC]
RewriteRule .* - [F,L]
# Block empty user agents
RewriteCond %{HTTP_USER_AGENT} ^-?$
RewriteRule .* - [F,L]Apache rate limiting with mod_evasive
.htaccess is fine for simple user-agent blocks, but real Apache rate limiting is normally vhost/server config, for example with mod_evasive:
DOSHashTableSize 3097
DOSPageCount 20
DOSPageInterval 1
DOSSiteCount 200
DOSSiteInterval 60
DOSBlockingPeriod 300
DOSLogDir /var/log/mod_evasiveNginx request limits
# http {} context
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
limit_req_zone $binary_remote_addr zone=search:10m rate=30r/m;
limit_req_zone $binary_remote_addr zone=general:20m rate=10r/s;
# server {} context
location ~* /(login|authentication|password-recovery) {
limit_req zone=login burst=3 nodelay;
try_files $uri $uri/ /index.php$is_args$args;
}
location ~* /(search|module/ps_facetedsearch|module/mprfilterrevolution) {
limit_req zone=search burst=20;
try_files $uri $uri/ /index.php$is_args$args;
}
location / {
limit_req zone=general burst=40;
try_files $uri $uri/ /index.php$is_args$args;
}fail2ban for brute-force protection
# Filter: /etc/fail2ban/filter.d/prestashop-login.conf
[Definition]
failregex = ^<HOST> .* "POST .*/login.*" (401|403)
# Jail: /etc/fail2ban/jail.d/prestashop.conf
[prestashop-login]
enabled = true
filter = prestashop-login
logpath = /var/log/apache2/access.log
maxretry = 10
findtime = 300
bantime = 3600Allowlist with care
- Payment providers: do not rate-limit or block payment callbacks, webhooks, 3-D Secure returns or order validation endpoints until you have their current IP ranges and tested real payments.
- Search engines: do not block Googlebot/Bingbot by user agent alone. Real search crawlers should be verified by reverse DNS or an equivalent verified-crawler mechanism, because fake bots reuse those names.
- CDN/reverse proxies: configure trusted proxy IPs first; otherwise every customer can appear as the proxy IP and one busy minute can block the whole shop.
- Back office and support IPs: allowlist narrowly and review regularly. A broad allowlist bypasses the protection you just added.
Security Revolution adds application-level protection for this layer: action limits for carts, registrations, contact and comments; global per-IP limits; per-crawler crawl budgets; a weighted limiter for expensive faceted listing requests; crawler management; bot-fight mode; and whitelisted IP configuration. Server rules still matter because they stop traffic before PHP, but the module gives the back office visibility into what was blocked.
Monitor your access logs
# Top 20 IPs by request count
awk '{print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | head -20
# IPs hitting login most
grep 'login' /var/log/apache2/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20Layering user-agent blocks, server rate limits, fail2ban, CAPTCHA, CDN protections and PrestaShop-aware module limits gives you most day-to-day bot protection without a paid WAF. For a broader checklist, see our PrestaShop security guide.
PrestaShop sends transactional emails, including order-state mail templates like the order confirmation, from editable template files on your server, so you can fully brand them. Here is the safe way to customize the order confirmation.
Each email has two files: an HTML version (what most customers see) and a plain-text fallback. They live in mails/<iso>/, one folder per language. The order confirmation is order_conf.html and order_conf.txt.
Edit a copy, never the core file:
- Copy
order_conf.htmlandorder_conf.txtfrommails/en/intothemes/your-theme/mails/en/(do the same per language). Theme templates take priority and survive core updates. - Build the layout with HTML tables and inline CSS, email clients ignore external stylesheets and modern layout. Set a fixed width (600px is standard) and keep it single-column for mobile.
- Insert data with curly-brace variables like
{order_name},{firstname},{total_paid}and{items}for the product list. To see which variables an email supports, check the PHP that sends it (order confirmation is built inclasses/PaymentModule.php).
Two things break confirmations most often: images with relative paths (use full https:// URLs) and unclosed table tags. And if emails arrive late or land in spam, the fix is usually delivery, not the template, switch from PHP mail() to authenticated SMTP under Advanced Parameters > E-mail. Full walkthrough in our PrestaShop email & SMTP guide.
A monthly 30-minute audit catches the small problems, outdated software, growing logs, silent errors, before they turn into slow pages, a breach, or downtime. Here is the focused checklist.
- PHP & config (3 min): run a supported PHP version; check
memory_limit(256M+),max_execution_timeand that OPcache is on. - Error logs (4 min): in Advanced Parameters > Logs scan the last week for Error/Critical entries; skim the PHP error log for fatals and deprecation notices.
- Modules (5 min): uninstall (don't just disable) modules you no longer use, and apply updates to payment and security modules first.
- Database (4 min): check total size and the usual bloated tables,
ps_connections,ps_guest,ps_cart,ps_log,ps_mail. Our Database Cleanup module purges these safely. - Security (5 min): confirm a randomised admin folder, valid SSL, sane file permissions (no 777), debug mode off in production.
- Performance (4 min): run a Lighthouse audit; verify Smarty cache and CCC are on in Advanced Parameters > Performance.
- SEO & backups (5 min): check robots.txt and the XML sitemap; confirm a recent, complete, offsite backup.
The audit identifies issues, it doesn't fix them. Fix security and broken functionality first, then performance and cleanup.
Map the audit to measurable module data where possible. Performance Revolution's cache stats separate PrestaShop query cache, module cache, Smarty, Symfony and OPcache, and OPcache reports scripts cached, memory usage, hits, misses and hit ratio. Its slow-query screen groups slow SQL by query hash and controller, so a monthly check can show whether one page or module is getting worse.
Database Cleanup is deliberately count-first. It reports cleanup candidates before deletion and uses limited batches for old carts older than 30 days with no order, search stats older than 90 days, expired specific prices, old logs, old connections, orphan guests and mail logs older than 30 days. Each task runs in batches and stops around a safety limit, so very large stores may need repeated runs rather than one huge delete.
For SEO, use the same audit to check whether robots.txt and sitemaps are coherent. SEO Revolution's sitemap verifier can skip URLs that are non-200, redirected, noindexed or canonical-mismatched, so a sudden drop in sitemap URLs is a signal to inspect response codes, canonicals and robots rules before assuming Google is at fault.
Fast monthly evidence list: OPcache hit ratio; slow queries last 24h; cleanup candidate counts; sitemap verified/skipped counts; latest backup timestamp.Other categories
Still have questions?
Can't find what you're looking for? Send us your question and we'll get back to you.