The common causes are calling setCustomVariable after trackPageView()/trackEvent() instead of before it, using a scope ("page" vs "visit") that does not match where you are viewing the data, or running on a Matomo install where Custom Variables have been superseded by Custom Dimensions - two separate features with separate configuration and reporting.
Why this happens
setCustomVariable(index, name, value, scope) attaches data to the next tracking request Matomo builds - it does not retroactively attach to a request already queued or sent, so call order matters strictly.
Separately, Matomo has moved its recommended approach from the older Custom Variables (limited slots, set via this API) to Custom Dimensions (configured per-site in the admin UI with a specific dimension ID, then set via setCustomDimension) in newer versions. Mixing the two, or expecting Custom Variable data in a Custom Dimensions report, is a frequent source of "my data just isn't there" that looks like a bug but is actually two different features.
Fix it
- Confirm which system your Matomo instance uses: check Administration > Websites > Manage > Custom Dimensions. If dimensions are configured there, use
_paq.push(["setCustomDimension", dimensionId, value]), not the legacy setCustomVariable. - If you are intentionally using legacy Custom Variables, call
_paq.push(["setCustomVariable", index, name, value, scope])immediately before the trackPageView/trackEvent call it should apply to - never after. - Match the scope argument ("visit" vs "page") to the report you are checking - a page-scoped variable will not appear in visit-level segments and vice versa.
- Confirm the Custom Variables plugin itself is still enabled (Administration > Plugins) - it is disabled by default on newer Matomo installs in favor of Custom Dimensions.
- Check the specific report page for custom variables or dimensions (Visitors > Custom Variables, or Visitors > Custom Dimensions) rather than expecting the value inside a generic pageview or event report.
How to verify it worked
Fire a test pageview or event with a custom variable or dimension set, then check the corresponding admin report filtered to the last few minutes - the value should appear as a new row. If it appears in the Visits Log's individual visit detail but not the aggregate report, scope mismatch is the remaining cause.