Separate visitor IDs recorded when using JS Site tag versus MatomoTracker.php

Hello! My site uses Matomo tracking and generally visits are recorded by the JavaScript tracking code on each webpage. I recently wrote a php script that records a file download action for directly downloaded files (hosted on the website) whose links are included in emails we send out.

Essentially, this php script runs on our site and its main query parameter is the actual URL to the file download. The script records the download action using MatomoTracker.php and then 302 forwards the user to the file URL.

This script is working to record the download events in Matomo, but I notice that the same user is recorded with a separate visitor ID when they visit our site directly versus when the action tracking happens through the MatomoTracker.php script - it’s me testing, so I know I’m the same user on the same machine, IP, etc. :slight_smile: I see the separate visitor IDs (and related actions) in the Matomo Dashboard.

Also, two separate _pk_id cookies are being recorded in the browser - I did notice that the one recorded by the JS site tag has a ‘.’ at the end, but maybe this makes no difference…


Same user visiting site directly and recorded by JS tag on site:

I assume the MatomoTracker.php has access to the Request object, but I am setting the following explicitly when I create the tracker object:

$t = new MatomoTracker($idSite, $siteName);

$t->setBrowserHasCookies(isset($_COOKIE) && !empty($_COOKIE));

Is there any way to get all the events tracked under one Visitor ID?

Thank you!

I re-read my previous post and find that it’s a bit rambling and possibly unclear. Here’s the summary / TLDR;

My site generally uses the typical JS based Matomo tracking tag without issues. I also have a use-case where I am using the PHP based MatomoTracker.php

If the same user/ip/machine/etc is recorded with the JS Tracking Tag and by MatomoTracker.php when using the site, separate VisitorIDs are recorded in Matomo when these actions should be for a single user.

Any ideas on how to solve this would be really appreciated. There’s more detail in the previous post. Thanks!


I thought I would provide this solution in case it may help anyone in the future. See above posts for description of the issue.

Essentially, after debugging, I found there was a cookie-domain name mismatch when tracking with the Matomo JavaScript tag on site webpages versus what was being recorded by MatomoTracker.php .

In my dev. environment, there was a typo in the Matomo JS tracking tag: ‘_paq.push([“setCookieDomain”, “*”]);’. Notice the ‘*.’ prior to ‘subdomain’.

When you specify a subdomain, you should not precede with a star. However (as an aside), if you want to match multiple subdomains, you may use a star (wildcard) in place of a subdomain: “*”.

The MatomoTracker.php was implicitly using my actual domain ‘’ (no star) as the cookie-domain, while the JS tracker was using ‘*’. This mismatched domain setting was causing different domainHashes to be calculated in the code and final cookie.

Incidentally, my production environment does use a star in the Matomo tracking tag: ‘_paq.push([“setCookieDomain”, “*”]);’.

I did not fully test, but I suspect this ‘*’ wildcard may cause a different domainHash as the JS code will internally remove the star and resolve the domain to ‘’ (notice the leading dot) whereas I suspect MatomoTracker.php will implicitely default to a domain of ‘’ (no leading dot). This dot difference will change the hash calculated and the cookie.

Anyway, the solution I came up with is to explicitly set the CookieDomain when using MatomoTracker.php to exactly match what is set by “setCookieDomain” in the webpage JS Matomo tag.

Here’s a generic example. Note that ‘$t’ is the tracker object in php (in my code). Explicitly calling enableCookies in MatomoTracker.php (I was not calling this function originally) allows you to exactly match the cookie-domain that is being used in the Matomo tracking tag and correctly track visitors when using JS and MatomoTracker.php on the same site.

$t->enableCookies(‘*’, //Cookie Domain - must match between PHP and JS tag on your site.
‘/’, //Path (example only - do what’s right for your site)
true, //Use secure cookie (example only - do what’s right for your site)
false, //Http only (example only - do what’s right for your site)
‘Lax’); //SameSite setting (example only - do what’s right for your site)