(written by Grok and reviewed by Max Milbers)

Audience: Template builders who override category browse / order-by
Files: vmbrowseorder.module.js, sublayouts/bs5-orderby.php, VirtueMartControllerCategory::browseSortUrl()

1. Why the links went away

VirtueMart 4 printed every sort as an <a href>. Name, price, date, manufacturer × ASC/DESC — each through JRoute. Search engines crawled extra URLs of the same products. SEF is SQL. A category page paid the router for options nobody clicked.

This is not a secret weapon. JS-first shops stopped putting sort permutations in the crawl graph years ago. PHP shops were late. VirtueMart 5 does the PHP version: the category HTML has a dropdown; JRoute runs once, when a human actually sorts.

We document it so your override does not print sixteen SEF links again “like VM4”.

2. How it works

  1. Markup: select#vm-orderby-select (and optional manufacturer select), data-vm-browse-* on the container. No sort <a href> in the default BS5 sublayout.
  2. Change → vmbrowseorder.module.js POSTs to view=category&task=browseSortUrl&format=json (POST, so Joomla SEF does not redirect the JSON endpoint and drop the base).
  3. PHP builds one SEF URL and returns { url: "…" }.
  4. The browser goes there.

Optional <noscript> GET form if you enable it. Crawlers that do not run JS see the category, not the sort mesh.

3. If you override order-by

  • Keep the dropdown + data-vm-browse-sort-task. Do not replace it with a list of JRouted links “for SEO” — that is the cost we removed.
  • The canonical category URL is enough for search engines. Sorted views are for shoppers.
  • Manufacturer filter uses the same module.

4. Do’s and don’ts

  • Do not GET the JSON task through SEF (the comment in the module is there because that produced a JSON page as HTML).
  • Do not invent a second sort event bus; VMInit already inits the module.