Skip to content

Store the partner id in the client metadata of setono/client-bundle instead of a plugin cookie - #61

Open
loevgaard wants to merge 1 commit into
3.xfrom
client-bundle-metadata
Open

Store the partner id in the client metadata of setono/client-bundle instead of a plugin cookie#61
loevgaard wants to merge 1 commit into
3.xfrom
client-bundle-metadata

Conversation

@loevgaard

Copy link
Copy Markdown
Member

What changed

The plugin no longer owns a cookie. The partner id captured from an affiliate link is stored in the metadata of the visitor's client provided by setono/client-bundle (v1.2), which recognises returning visitors through its own setono_client_id cookie and persists changed metadata itself at kernel.finish_request.

  • PartnerIdStorage\PartnerIdStorageInterface (store(int), get(): ?int) with ClientMetadataPartnerIdStorage: writes the id under the namespaced key setono_sylius_partner_ads.partner_id with the attribution window as TTL; on read it re-validates through PartnerIdParser and deliberately never removes an invalid value (a write at checkout would make the bundle flush during checkout). Same pattern as SyliusGoogleAdsPlugin.
  • EventListener\CapturePartnerIdSubscriber (replaces SetCookieSubscriber) on kernel.request: same guards and validation as before, then store(). Last click wins.
  • CreateConversionSubscriber reads through the storage; the RequestStack dependency is gone. Its docblock now explains the checkout-time cost: one lazy SELECT by the bundle, no writes (an expired key is pruned and persisted by the bundle after the order is committed).
  • Config: the cookie node (name, expire) is removed; attribution_window (days, default 40, min 1) replaces cookie.expire.
  • Dependencies: setono/client-bundle ^1.2 and setono/client ^1.1.2 added; symfony/http-foundation no longer required directly. The test application registers SetonoClientBundle.

Breaking changes

  • Removed: CookieHandler\CookieHandler, CookieHandler\CookieHandlerInterface, EventListener\SetCookieSubscriber (the BC job flags exactly these — expected on 3.x).
  • Configuration cookie.* removed; attribution_window added.
  • Applications must register SetonoClientBundle and migrate (setono_client__metadata).
  • Attributions in flight at upgrade time are lost: the 2.x cookie is ignored, not imported (maintainer decision), and simply expires.

All of this is in UPGRADE.md; the README gained the bundle registration step, an attribution-window step and a "Consent and privacy" section (consent via the bundle's PreStoreCookieEvent); CLAUDE.md is updated accordingly.

Tests

  • New ClientMetadataPartnerIdStorageTest (TTL arithmetic, overwrite/restart, expiry, invalid stored values remain untouched), CapturePartnerIdSubscriberTest, a kernel-boot PartnerIdStorageTest proving bundle registration and wiring (no database needed); CreateConversionSubscriberTest, ConfigurationTest (incl. rejecting the removed cookie node) and the extension test updated; cookie tests removed.
  • ECS, PHPStan (level max), lint:container, doctrine:schema:validate (with setono_client__metadata created), 172 tests, and Infection at 100% on the changed files all pass locally.

Closes #53 once merged: the plugin sets no cookie any more; consent and the IP disclosure are documented. The Secure flag question now concerns the bundle's cookie.

The plugin no longer sets a cookie of its own. The partner id captured
from the affiliate link is stored in the metadata of the visitor's
client (setono/client-bundle), which recognises returning visitors
through its own cookie and persists changed metadata itself at the end
of the request. A small PartnerIdStorageInterface keeps the subscribers
independent of the bundle and makes the storage swappable.

The attribution window stays configurable in days (attribution_window,
default 40) and becomes the metadata key's TTL. The legacy 2.x cookie is
not imported; UPGRADE.md says so.

Claude-Session: https://claude.ai/code/session_01Mt12J8vdGwwWg4V23uoEf9
@codecov

codecov Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 84.24%. Comparing base (749cbab) to head (471ab6f).

Additional details and impacted files
@@             Coverage Diff              @@
##                3.x      #61      +/-   ##
============================================
- Coverage     84.85%   84.24%   -0.62%     
+ Complexity      101       99       -2     
============================================
  Files            21       21              
  Lines           535      514      -21     
============================================
- Hits            454      433      -21     
  Misses           81       81              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cookie hardening: set Secure flag and document consent/GDPR implications

1 participant