Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
New integration that syncs Fides consent with Matomo's tracking consent and cookie consent APIs via _paq.push(). Follows the Gen 2 integration pattern (same as GCM, AEP, BlueConic). Key behavior: requireConsent is conditionally activated based on the presence of the consent key in the Fides consent object, matching GCM's pattern. This correctly handles both OMIT and INCLUDE non-applicable flag modes without any user configuration. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add _paq stub to Cypress visitConsentDemo command - Add Fides.matomo() call to fides-js-components-demo.html - Add Matomo test section to consent-third-party.cy.ts covering: - _paq exists on window - No commands pushed when analytics key is absent - requireConsent + forgetConsentGiven on init with opt-out default - rememberConsentGiven after user opts in via banner Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bc3b9c2 to
5411855
Compare
|
/code-review |
|
Re: missing test for |
- Capture _paq reference once, remove non-null assertions - Document hardcoded consent key limitation in customer-facing docs - Use optional chaining in demo HTML - Remove tautological Cypress test - Add missing test for consentMode "both" + rememberConsent false - Regenerate typedoc markdown Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
/code-review |
There was a problem hiding this comment.
Code Review: Fides.matomo() integration helper
The core implementation in matomo.ts is clean and well-structured. It follows the established Gen 2 integration pattern accurately, the module decomposition (pushRequireConsent / pushConsentUpdate / findConsentKey) is clear, and the 26 unit tests cover the key behavioral paths well. The JSDoc examples are thorough and the changelog entry is correct.
Must Fix
Misleading Cypress test name (inline comment on consent-third-party.cy.ts:531): The test is named "pushes requireConsent on FidesReady when analytics key is present" but asserts the opposite — no calls when the key is absent. Quick one-line rename.
Should Address
Unconditional matomo() call in demo page (inline comment on fides-js-components-demo.html:223): The previous gtm() call used an explicit falsy guard (!!window.fides_overrides && window.fides_overrides.gtmOptions) that passed false when the option was absent. Both gtm() and matomo() now receive undefined via optional chaining, which causes them to apply defaults and run unconditionally. For matomo() this silently initializes _paq and pushes requireConsent on every page load even without intent. The demo page is a reference pattern for integrators; guarding with if (window.fides_overrides?.matomoOptions) would restore the original semantics.
Test isolation fragility (inline comment on matomo.test.ts:67): The comment documents a real, unresolved ordering dependency — subscribeToConsent listeners cannot be cleaned up, so each matomo() call in tests accumulates permanent window event handlers. The current suite is safe only because this describe block runs first. Adding any new matomo() call above it would silently corrupt the assertion. If returning an unsubscribe function from subscribeToConsent is feasible, it would fix this for all integrations. At minimum the comment should be more explicit about the file-level ordering invariant.
Suggestions
requireConsentPushedis per-instance, not per-_paq(inline comment onmatomo.ts:124): Ifmatomo()is called twice, both closures pushrequireConsentand both consent commands on each event. Worth a doc note or a single-call guard.DEFAULT_CONSENT_KEYSis not configurable (inline comment onmatomo.ts:45): Sites with non-standard consent key names silently fall to free-tracking mode. An optionalconsentKeysoverride inMatomoOptionswould be additive and non-breaking.EMPTY_BUNDLEsuppression lacks a comment (inline comment onrollup.config.mjs:316): A one-line comment explaining why the warning is expected would prevent future confusion.
🔬 Codegraph: unavailable
💡 Write /code-review in a comment to re-run this review.
- Fix misleading Cypress test name (says "present", tests "absent") - Use module-level WeakSet guard for requireConsentPushed to prevent double-push when matomo() is called multiple times - Add explanatory comment for EMPTY_BUNDLE rollup suppression Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
|
||
| const DEFAULT_CONSENT_KEYS = ["analytics", "performance"]; | ||
|
|
||
| const paqsWithRequireConsent = new WeakSet<unknown[][]>(); |
There was a problem hiding this comment.
I'm curious what the rationale behind both WeakSet and this not being some sort of flag-like value is?
There was a problem hiding this comment.
Good question. The WeakSet came from a Claude Code review suggestion - it flagged that the original per-closure boolean would allow duplicate requireConsent pushes if matomo() was called more than once. I moved the guard to module scope per that review, and went with WeakSet keyed on the _paq array reference so it auto-resets if window._paq is ever replaced.
That said, none of our other integrations (GCM, AEP, BlueConic, GTM, Shopify) use this kind of guard or worry about the global array being swapped out. A simple let requireConsentPushed = false boolean would be more consistent with the rest of the codebase and easier to grok. Happy to simplify if you'd prefer that.
| paq.push([command]); | ||
| fidesDebugger(`[Fides Matomo] Pushed ${command}`); | ||
| } else { | ||
| paq.push(["forgetConsentGiven"]); |
There was a problem hiding this comment.
Should we always push forgetConsentGiven when analytics is false? I'd need to check Matomo's behavior but I can imagine a scenario in which a client using this extension could swap it's default behavior to just cookie for instance, deploy that change. Then a data subject could go opt out of analytics and we'd never push forgetConsentGiven I also wonder if Fides sees tracking as false whether it should also push forgetConsentGiven?
There was a problem hiding this comment.
Good catch. Matomo's forgetConsentGiven/forgetCookieConsentGiven are safe no-ops when consent was never granted, so I'll always push both revoke commands regardless of consentMode and only gate the grant path.
| if (granted) { | ||
| const command = rememberConsent | ||
| ? "rememberCookieConsentGiven" | ||
| : "setCookieConsentGiven"; | ||
| paq.push([command]); | ||
| fidesDebugger(`[Fides Matomo] Pushed ${command}`); | ||
| } else { | ||
| paq.push(["forgetCookieConsentGiven"]); | ||
| fidesDebugger("[Fides Matomo] Pushed forgetCookieConsentGiven"); | ||
| } |
There was a problem hiding this comment.
Roughly same question as here: https://github.com/ethyca/fides/pull/7991/changes#r3126548623
There was a problem hiding this comment.
Addressed in the same change as the tracking side fix above. Revoke commands will always push for both consent types regardless of consentMode.
| paq: unknown[][], | ||
| consentMode: MatomoConsentMode, | ||
| ): void => { | ||
| if (consentMode === "tracking" || consentMode === "both") { |
There was a problem hiding this comment.
This is a small file and I don't think it's likely to change but IMO these checks would be better packaged into something like
object MatomoDecisions(consentMode) {
ctor() {
this.consentMode = consentMode
}
isTracking() {
return consentMode === "tracking" || consentMode === "both";
}
/* etc */
}
// Usage
/* initialize matomoDecision object */
if (matomoDecision.isTracking()) { /* dostuff */ }
There was a problem hiding this comment.
Done! Extracted consentModeChecks(consentMode) with isTracking() and isCookie() helpers, used in both pushRequireConsent and pushConsentUpdate.
- Always push both forgetConsentGiven and forgetCookieConsentGiven on revoke regardless of consentMode to clean up stale consent cookies - Extract consentModeChecks() helper for isTracking/isCookie checks Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ticket ENG-3295
Description Of Changes
New
Fides.matomo()integration helper that automatically syncs Fides consent decisions with Matomo's tracking consent and cookie consent APIs via_paq.push(). Follows the same Gen 2 integration pattern asFides.gcm(),Fides.aep(), andFides.blueconic().Key design decisions:
requireConsent: Rather than always calling Matomo'srequireConsent()on init (which would block tracking for users in non-consent regions), the integration defers this call until the first consent event where theanalyticsorperformancekey is present in the Fides consent object. This follows GCM'sincheck pattern and correctly handles bothOMIT(default) andINCLUDEnon-applicable flag modes without any user configuration.requireConsentoption: Unlike the original PRD spec, this option was removed. All other Fides integrations (GCM, AEP, BlueConic, Shopify) let Fides handle jurisdiction awareness rather than exposing a toggle. The conditional activation approach achieves the same goal automatically.rememberConsentdefaults totrue: Uses Matomo'srememberConsentGiven()to persist consent via Matomo'smtm_consentcookie, so tracking can resume on page loads before Fides initializes.Public API:
Code Changes
clients/fides-js/src/integrations/matomo.ts- core integrationclients/fides-js/__tests__/integrations/matomo.test.ts- 26 unit testsclients/fides-js/src/lib/consent-types.ts- addmatomotoFidesGlobalclients/fides-js/src/lib/init-utils.ts- wirematomointogetCoreFides()clients/fides-js/src/docs/fides.ts- JSDoc forFides.matomo()consent-third-party.cy.tsfor the Matomo integration_paqstub to CypressvisitConsentDemocommandFides.matomo()call tofides-js-components-demo.htmlSteps to Confirm
Automated:
cd clients/fides-js && npx jest __tests__/integrations/matomo.test.ts- 26 unit tests passcd clients/fides-js && npm run check- lint, format, typecheck all passcd clients/fides-js && npm run build- build succeedsconsent-third-party.cy.tsMatomo tests passManual (demo page):
Use https://developer.matomo.org/guides/tracking-consent for reference
http://localhost:3001/fides-js-demo.htmlFides.matomo()in the consolewindow._paq- should contain["requireConsent"]followed by a grant or revoke command depending on the default consent statewindow._paq- should see["rememberConsentGiven"]after accepting or["forgetConsentGiven"]after rejectingFides.matomo({ consentMode: "both" })- should see both tracking and cookie consent commandsFides.matomo({ rememberConsent: false })- should see["setConsentGiven"]instead of["rememberConsentGiven"]Pre-Merge Checklist
CHANGELOG.mdupdatedmaindowngrade()migration is correct and works