Compare for Craft CMS

Troubleshooting

The compare button does nothing

Check the element is in a set. In a template:

{{ craft.compare.setFor(product) ? 'in set: ' ~ craft.compare.setFor(product).handle : 'NO SET' }}

craft.compare.button() returns nothing at all when the element matches no set — so an empty space where a button should be almost always means the set's sources do not include that element's section or product type.

Check the runtime loaded. The bundle is registered by button() and bar(), and only on pages that render one. If you built your own controls with data attributes and nothing else, call {{ craft.compare.registerAssets() }} yourself.

Check the browser console. With JavaScript failing, the button still works — it submits the form and reloads the page. If clicking reloads the page, the runtime is not running.

The count is wrong on a cached page

It shouldn't be — that is what the session endpoint is for. If it is:

  • Confirm /compare/session.json returns JSON with a csrfToken and your real counts.
  • Confirm your CDN or reverse proxy is not caching that URL. Compare sends Cache-Control: no-store, private, but a proxy configured to cache aggressively by extension can still do it. session.json ends in .json, which some rules treat as a static asset.

"The comparison table is empty"

Work down this list:

  1. Does the set have rows? A set with none draws an empty table. The set editor refuses to save without at least one.
  2. Do the elements answer any of them? Rows no element answers are dropped. A table of three products where every configured field is empty renders nothing.
  3. Are the elements in the set? craft.compare.render(entries) silently drops anything the set does not match, so passing the wrong section gives you an empty table rather than an error.
  4. Is "differences only" on? If every row agrees, the differences-only view is legitimately empty. It says so.

A row shows a blank for one element

That is by design when the field is not on that element's field layout — a set spanning two entry types where only one has screenSize gives the other a blank. The blank counts as a difference, which is usually what you want.

If it is blank for every element, check the field handle in the row's settings. A renamed field leaves the row pointing at a handle that no longer exists; Compare logs a warning rather than throwing, so look in storage/logs for compare.

Price, SKU or stock rows are missing from the row-type list

Those rows only appear when the set's element type is a Commerce Product or Variant. Change the element type at the top of the set editor and the row list repopulates immediately.

If they are missing even for a product set, Commerce is not installed or not enabled.

Everything shows "Out of stock"

Check whether the purchasable has inventory tracking switched on in Commerce. Compare treats an untracked purchasable as available, not as zero — but if tracking is on and stock is genuinely 0, that is Commerce's answer, not Compare's.

Switch the Stock row to "the number in stock" to see the figure it is reading.

The guest's list vanishes when they sign in

It should merge. If it does not:

  • The guest list and the user list must be for the same set on the same site. A list built on the German site does not merge into the English one.
  • Check storage/logs for Could not merge the guest compare list on login — the merge is wrapped so a failure can never stop somebody logging in, and it logs instead.

Note the deliberate behaviour when both lists exist: the user's saved list is kept and the guest's items are appended up to the cap. Extras beyond the cap are dropped silently, because this happens on a login redirect where there is nowhere to say anything, and evicting something the user deliberately saved would be worse.

A signed-in user gets somebody else's comparison

This should be impossible: adopting a guest list clears its token, so the cookie stops resolving to anything. If you see it, check that nothing outside Compare is writing the CraftCompareToken cookie, and that defaultCookieDomain is not set so broadly that two unrelated sites share it.

Sharing says it's a Pro feature

It is. So are difference highlighting, the "differences only" toggle, Twig template rows, more than one set, more than three items, and Insights.

On a lapsed Pro licence the table narrows to three columns and Twig rows are skipped rather than erroring — stored lists and sets are untouched, and renewing restores them.

The comparison page 404s

The page URI (default compare) must not clash with an entry URI on any site. If you have an entry at /compare, Craft's element routing wins. Change the URI in Settings → Plugins → Compare.

Insights are empty

  • Insights are Pro.
  • Record insights must be on.
  • Only comparisons are recorded, not additions to a list: two or more elements have to be seen side by side. A visitor who adds one product and leaves records an "add" and no head-to-head.
  • Events older than the retention period are swept by garbage collection.

Getting more detail

Compare logs under the compare category:

grep compare storage/logs/web.log
php craft compare        # what Compare currently holds