-
Notifications
You must be signed in to change notification settings - Fork 0
Comparing changes
Open a pull request
base repository: schorschii/matomo-php-tracker
base: master
head repository: matomo-org/matomo-php-tracker
compare: master
- 7 commits
- 14 files changed
- 10 contributors
Commits on Dec 2, 2025
-
Configuration menu - View commit details
-
Copy full SHA for 9ddccf0 - Browse repository at this point
Copy the full SHA 9ddccf0View commit details
Commits on Dec 12, 2025
-
Declare supported PHP versions explicitly and run tests on all suppor…
…ted versions (matomo-org#147) * Declare supported PHP versions explicitly and run tests on all supported versions * Apply suggestion from @sgiehl --------- Co-authored-by: Stefan Giehl <stefan@matomo.org>
Configuration menu - View commit details
-
Copy full SHA for b029aa2 - Browse repository at this point
Copy the full SHA b029aa2View commit details
Commits on Dec 20, 2025
-
Fix: Not possible to create multiple Piwik tracker instances having d…
…ifferent API urls (matomo-org#145) * Allow setting form factors client hint (matomo-org#136) * Allow settting form factors client hint * update changelog * Fix handling of some attributes * Apply review feedback Co-authored-by: Michal Kleiner <mk@011.nz> --------- Co-authored-by: Michal Kleiner <mk@011.nz> * deprecate $URL * use old $URL if apiUrl is empty --------- Co-authored-by: Stefan Giehl <stefan@matomo.org> Co-authored-by: Michal Kleiner <mk@011.nz> Co-authored-by: Andrii Lutskevych <andrii.lutskevych@check24.de>
Configuration menu - View commit details
-
Copy full SHA for 9462dc6 - Browse repository at this point
Copy the full SHA 9462dc6View commit details
Commits on Jan 16, 2026
-
Conditionally close the curl handle (matomo-org#150)
`curl_close` has no effect since PHP 8.0 and is deprecated since 8.5 https://www.php.net/curl_close
Configuration menu - View commit details
-
Copy full SHA for 262acfd - Browse repository at this point
Copy the full SHA 262acfdView commit details
Commits on Jul 24, 2026
-
Add method to track an AI bot request, if the current user agent is a…
… known AI bot (matomo-org#148) * add methods to detect and track pageviews if the current user agent is an AI bot * add supported query parameters for AI bot tracking * add more tests for AI bot tracking methods * use recMode parameter * make user agent substrings array a public const and fill out missing php docs * remove phpstorm added spacing * update tests * set url in test * remove Devin user agent check Co-authored-by: Thomas ZILLIOX <thomas@zilliox.me> * Apply suggestions from code review Co-authored-by: Stefan Giehl <stefan@matomo.org> --------- Co-authored-by: Thomas ZILLIOX <thomas@zilliox.me> Co-authored-by: Stefan Giehl <stefan@matomo.org>
Configuration menu - View commit details
-
Copy full SHA for f2afbb8 - Browse repository at this point
Copy the full SHA f2afbb8View commit details
Commits on Jul 27, 2026
-
Modernize tracker for 4.0.0: PHP 8.1, strict types, static analysis, …
…full test coverage (matomo-org#152) * Raise PHP requirement to 8.1 and add static-analysis dev tooling - Drop PHP 7.2-8.0 support; require ^8.1. - Bump PHPUnit to ^10.5 (PHP 8.1 floor rules out PHPUnit 11). - Add PHPStan ^2, PHP_CodeSniffer ^3.10, the Matomo coding standard (matomo-org/matomo-coding-standards via VCS repo) and the phpcs composer-installer plugin. - Pin config.platform.php to 8.1.0 and allow the installer plugin. - Add composer scripts: test, phpstan, phpcs, phpcbf. * CI: run on PHP 8.1-8.5 and add PHPStan + PHPCS quality workflow - phpunit.yml: drop PHP 7.2-8.0 from the matrix, bump to actions/checkout@v4, and install the json + curl extensions. - Add quality.yml running PHPStan and PHP_CodeSniffer on PHP 8.1 for every pull request and push to master. * Add strict types and modern type hints; fix latent type bugs Add declare(strict_types=1) to both source files and give every method proper parameter and return type hints aligned with how Matomo core coerces each tracking parameter. Declare all class properties explicitly with concrete/nullable types and array-shape PHPDocs (the class keeps #[AllowDynamicProperties] for consumer BC). Optional 'unset' parameters and their backing properties/getters move from the legacy `= false` sentinel to nullable (`?T = null`); fluent setters now declare `: self`, and the do* tracking methods declare `: string|bool`. Fixes latent type issues that become fatal TypeErrors under strict types (previously masked by weak-mode coercion), including: - sendRequest() now returns string|bool (bulk mode really returns true, not the coerced "1"); cascaded to all do* methods. - forceDotAsSeparatorForDecimalPoint() no longer returns null/false from a : string method. - setCustomTrackingParameter() casts the dimension id to int. - doTrackSiteSearch()/getUrlTrackSiteSearch() use ?int and only emit &search_count when a count is provided (no longer always sends 0). - getUrlTrackCrash()/getUrlTrackEcommerceOrder() cast int/id values before urlencode(); getRequest() casts lat/long before urlencode(). - getUrlTrackEvent() guards the nullable name/value correctly. - clientHints is reset to [] (not false) in bulk mode. - getCustomVariablesFromCookie() validates decoded cookie data. BREAKING CHANGE: passing mismatched scalar types now throws TypeError instead of being silently coerced, and unset sentinels are null rather than false. This targets a new major release. * Add PHPStan configuration at max level Analyse both source files at level max with the PHP 8.1 platform. No baseline: the codebase is fully clean at max level. * Add PHP_CodeSniffer config (Matomo standard) and fix violations Add phpcs.xml.dist referencing the Matomo coding standard with a 400-char line limit and scoped exceptions: the two source files intentionally mix a class with global helper functions/includes and stay in the global namespace for backwards compatibility. Apply the resulting fixes (blank line after the open tag, control structure / operator spacing, trailing newline) and clean up the test file: reorder the file header, add constant visibility, and rename the test methods to camelCase. * Migrate PHPUnit configuration to 10.x and update tests - phpunit.xml.dist: run --migrate-configuration (drop the removed verbose attribute, refresh the schema to 10.5, add cacheDirectory); keep backupGlobals. - Make the data-provider methods static as required by PHPUnit 10. - Ignore the new .phpunit.cache directory. * Document PHP 8.1 requirement and the 4.0.0 major release - README: state the PHP 8.1+ requirement and add a Development section covering the composer test/phpstan/phpcs scripts. - CHANGELOG: add the 4.0.0 entry describing the breaking changes (PHP floor, strict types, false->null sentinels, do* return type, search_count / stream-fallback behaviour) and the new tooling. - .gitattributes: export-ignore phpstan.neon.dist and phpcs.xml.dist so dist archives stay lean. * Remove #[AllowDynamicProperties] All properties are now declared explicitly, so the tracker no longer creates dynamic properties and the attribute is unnecessary. Dropping it makes undeclared dynamic property writes raise the standard PHP 8.2 deprecation, in line with the strict, fully-typed rewrite. * Allow setUserId(null) to de-assign a previously set User ID The method documentation always promised that the User ID can be unset again, but the string type hint made that impossible. Accept null to reset it, matching the null sentinel used everywhere else. * Fix issues found in adversarial review - Cast cookie names to string before strpos(): cookies with purely numeric names are exposed as integer keys in $_COOKIE and caused a TypeError under strict_types, breaking tracker construction. - Do not read $http_response_header when the stream fallback request failed without an HTTP response; previously this caused a TypeError in parseIncomingCookies() instead of returning false. - Send latitude/longitude values of 0.0 instead of silently dropping coordinates on the equator or prime meridian. - Guard the POST URL split against URLs without a query string and replace an always-true elseif condition with else. - Remove dead branches in setEcommerceView() that guarded against values the string type hints now make impossible. - Restore the dropped $category docblock in doTrackSiteSearch(), fix the setClientHints() fullVersionList docblock shape, remove leftover array() syntax and strval() calls, and document all behavior changes in the 4.0.0 changelog. * Greatly expand the unit test suite and report coverage in CI - Add tests for every tracking URL parameter, all do*/getUrlTrack* methods, custom variables/dimensions, ecommerce, client hints, attribution info, visitor/user id handling, bulk tracking, cookie handling and request preparation, including regression tests for the behavior changes of the 4.0.0 release (search_count omission, bulk true return, null sentinels, numeric cookie names). - Introduce a TestableMatomoTracker capturing requests and cookies instead of performing network or header I/O. - Analyse the test suite with PHPStan at max level. - Add a phpunit <source> section and a CI coverage job (pcov). * Improve compatibility with Matomo's tracker usage; add test-only raw param helper Findings from auditing tracker usage across Matomo core and plugins: - setUrlReferrer()/setUrlReferer() accept ?string again so callers can unset the referrer with null (used by several Matomo fixtures). - setCustomTrackingParameter() accepts string|array again; array values are serialized via http_build_query exactly as before 4.0.0, restoring multi-value parameters used by FormAnalytics and HeatmapSessionRecording. - Add setDebugTrackingParameter(string, string) (@internal): appends a raw, unvalidated parameter that overrides any built-in of the same name, so Matomo integration tests can verify server-side handling of malformed values without bypassing the tracker. Cleared per request. Adds unit tests and CHANGELOG entries for all three. * CI: harden workflows (pin setup-php, disable credential persistence) - Pin shivammathur/setup-php to a commit hash (2.37.2) instead of the floating @v2 tag, mitigating supply-chain risk (Aikido high finding). - Set persist-credentials: false on actions/checkout steps so the GITHUB_TOKEN is not left in the git config for later steps (Aikido). * CI: remove the code coverage job Drop the pcov-based coverage job for now; the standard PHPUnit matrix, PHPStan and PHPCS jobs remain. * Distinguish unset from zero for goal/ecommerce revenue amounts Core treats an absent 'revenue' as 'use the goal's configured revenue', and defaults the optional ecommerce amounts to false (not 0), so a real zero is meaningful and must be distinguishable from 'not provided'. - doTrackGoal()/getUrlTrackGoal() (+ Matomo_/Piwik_ helpers) take ?float $revenue = null: null omits revenue, 0.0 now sends revenue=0. - doTrackEcommerceOrder()/getUrlTrackEcommerceOrder()/getUrlTrackEcommerce() take ?float $subTotal/$tax/$shipping/$discount = null, sent only when provided; the required grand total is now always sent (0.0 -> revenue=0). Previously an explicit 0/0.0 was silently dropped by the !empty() guards. Adds tests and a CHANGELOG entry. * Address open issues: URL-encode cip (matomo-org#151), drop dead curl_close (matomo-org#149) - URL-encode the cip (override IP) tracking parameter before adding it to the request, matching every other value and preventing tracking-parameter injection when an application sets cip from untrusted input. Fixes matomo-org#151. - Remove the curl_close() call guarded by PHP_VERSION_ID < 80000: it is dead code now that PHP 8.1 is the minimum, and curl_close() is a no-op (and deprecated in PHP 8.5) on all supported versions. Fixes matomo-org#149. * Send ca=1 on event and content tracking requests (matomo-org#80) Append &ca=1 (custom action) to the event and content-tracking URLs, matching the JS tracker. This prevents Matomo from falling back to recording these requests as page views when the handling plugin is disabled. Fixes matomo-org#80. * Lower default request timeouts to sane in-page values (matomo-org#88) Change the default requestTimeout from 600s to 5s and connect timeout from 300s to 2s, so a slow or unreachable Matomo can no longer block the calling page for up to 10 minutes. Callers can still raise them via setRequestTimeout()/setRequestConnectTimeout(). Fixes matomo-org#88. * Add setCurlOptions() for custom cURL options (matomo-org#92) Allow callers to pass additional cURL options (e.g. CURLOPT_IPRESOLVE, CURLOPT_HTTP_VERSION) that are applied after the built-in options, so they can tune the request without the library committing to opinionated defaults. Fixes matomo-org#92. * Unify request-failure handling; add opt-in fail-safe mode (matomo-org#105) Previously the cURL transport threw a RuntimeException on DNS/connection failures while the stream transport silently returned false. Both now throw by default (preserving cURL behavior and making the two transports consistent). Call setExceptionsEnabled(false) to make failed requests return false instead, so tracking never breaks the calling application. Refs matomo-org#105. * Consistently encode tracking parameters; keep the request URL out of exceptions - URL-encode the remaining raw query values: _refts (from attribution data), customData (data) and pageCharset (cs), so a value can no longer inject extra tracking parameters. - Validate the visitor ID read from the first-party cookie as a 16-character hexadecimal string in loadVisitorIdCookie(), matching setVisitorId(). - Request-failure exceptions now include only the target host, never the full URL (which can carry token_auth/PII in its query string). * Fix cookie header serialization/parsing; redact attribution exception - Build the outgoing Cookie header as url-encoded pairs joined with '; ' (was http_build_query, which joined with '&'), and parse every incoming Set-Cookie header by its first '=' so multiple cookies accumulate (parse_str previously overwrote the whole set per header and applied query-string bracket semantics). getIncomingTrackerCookie() now returns string|false. - setAttributionInfo() no longer echoes the supplied JSON in its exception message and marks the parameter #[\SensitiveParameter]. * Address security-review findings (sensitive params, POST token, transports, bulk) - Mark sendRequest() $url and $data as #[\SensitiveParameter] so they are redacted from exception stack traces (token_auth/PII). - Force POST when token_auth is placed in the request body, so the stream transport no longer sends it as a GET body that Matomo ignores. - Stream transport sets ignore_errors so HTTP 4xx/5xx return the response body (parity with cURL) instead of a failure. - Bulk tracking uses a >=30s timeout and retains the queued actions when a batch fails to send (previously discarded), allowing retry. - Docs: clarify setUserId(null) does not unlink the current server-side visit; drop the stale 'coverage reported in CI' CHANGELOG claim. Adds tests for all of the above. * Encode the action type and harden the transport selection - getUrlTrackAction()/doTrackAction() now URL-encode the action type (not just the value), so a crafted or plugin-specific action parameter cannot inject an additional query-string parameter. - Extract the visitor-id hex character set into a single HEX_CHARACTERS constant used by both setVisitorId() and loadVisitorIdCookie(). - Make cURL detection overridable via hasCurlSupport() so the stream transport can be exercised in tests; add coverage for the stream failure (host-only exception message) and fail-safe paths. * Document error handling/timeouts and clarify config comments - README: add an 'Error handling and timeouts' section covering the default exceptions, the short 5s/2s timeouts, setExceptionsEnabled(), setRequestTimeout()/setRequestConnectTimeout() and bulk retention. - CHANGELOG: correct the multi-value BC note to reference pre-3.4.0 and mention that the download/link action type is now URL-encoded. - phpcs.xml.dist: explain that the 400-char line limit matches Matomo core's own coding standard rather than being an arbitrary value. * Mark request URL/body sensitive in the transport option builders sendRequest() appends token_auth into the URL/body and passes them to prepareCurlOptions()/prepareStreamOptions(). #[\SensitiveParameter] only redacts the frame where the parameter is declared, so mark those params too: should either builder (or something it calls) ever throw, the token and PII carried in $url/$data are redacted from that frame as well. * CHANGELOG: warn that the removed false sentinel now coerces to 0/'' The blanket 'mismatched scalar now throws a TypeError' claim was misleading: strict/weak mode is set by the *caller's* file, so a normal (non-strict) consumer still gets weak-mode coercion. Legacy calls that passed false to mean 'not known' (doTrackEvent value, addEcommerceItem price, setLatitude/setLongitude, ...) now silently send 0/0.0/'' instead of omitting the parameter. Add an explicit upgrade note and correct the TypeError wording so the transition is spelled out. * Merge custom CURLOPT_HTTPHEADER instead of replacing the built-in headers setCurlOptions() applied caller options via array_replace(), so a caller adding a single header wholesale-replaced the tracker's own header list. For POST/bulk requests that dropped the Content-Type, making Matomo unable to parse the body — a silent failure. Merge (append) custom HTTP headers onto the built-in ones instead, and document the special-casing. Also extend the sensitive-parameter test to assert redaction on the transport option builders (prepareCurlOptions/prepareStreamOptions), not just sendRequest, since the URL/body are forwarded to them.
Configuration menu - View commit details
-
Copy full SHA for bde2d19 - Browse repository at this point
Copy the full SHA bde2d19View commit details -
Detect Google-GeminiNotebook as an AI bot (matomo-org#153)
* Apply Google-GeminiNotebook update * Detect Google-GeminiNotebook user agent --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for b3e57c4 - Browse repository at this point
Copy the full SHA b3e57c4View commit details
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff master...master