medelse/referer-cookie-bundle
A Symfony bundle that captures the HTTP referer in a cookie, making referral information persist across requests for attribution, redirects, or analytics.
This is a Symfony bundle, not a Laravel package — the first thing to verify before you plan any integration work. It is designed to hook into Symfony's HTTP kernel (via config/bundles.php and an event subscriber on kernel.request) and to persist the incoming Referer header into a cookie so it survives across the user's session. If you are on Laravel, there is no native path: you would be reimplementing the behaviour with a middleware, so treat the repo as a reference implementation rather than a dependency.
For a Symfony project:
composer require medelse/referer-cookie-bundle (requires a PHP/Symfony constraint compatible with your app — check composer.json of the package first, since the last release is 2021 and predates Symfony 6/7 support).config/bundles.php (or app/AppKernel.php on older Symfony).DependencyInjection/Configuration.php and Resources/config/services.yaml — that is where the cookie name, lifetime, path, and domain options live (typically exposed under a medelse_referer_cookie: key in config/packages/).Minimal config shape you should expect:
# config/packages/medelse_referer_cookie.yaml
medelse_referer_cookie:
cookie_name: referer
lifetime: 2592000 # 30 days
path: /
domain: ~
And the read side, once the subscriber has run:
$referer = $request->cookies->get('referer');
Attribution capture on first touch. The bundle's subscriber runs on every request and writes the cookie when a referer is present. Because it overwrites on each request, the cookie reflects the most recent external referer, not the first. If you need first-touch attribution, capture the value once (e.g. in your own kernel.request listener with a lower priority or in a controller on the landing route) and copy it to a durable field, rather than relying on the bundle cookie remaining stable.
Reading at conversion time. The practical workflow is: landing → cookie set → user registers or checks out → your controller/service reads $request->cookies->get('referer') and persists it alongside the user or order record. Wire this into your registration handler or an Order entity listener so the value is captured at write time, not computed on read.
Consolidating with UTM parameters. The referer alone is coarse (it gives you https://partner.example/path but not campaign). Pair the cookie with utm_source/utm_medium query params using the same lifetime and cookie scope so attribution records are consistent. A common pattern is a single subscriber that writes a JSON-encoded attribution cookie containing referer + UTMs + landing URL + timestamp.
Customising the cookie scope. Most bundles of this shape let you override name, domain, path, and SameSite. Set domain: .example.com if you need the cookie shared across subdomains (www → app). Set a longer lifetime (90 days is typical for B2B) if the default is short.
Extension point. If the bundle's config doesn't expose what you need (e.g. Secure/HttpOnly flags or SameSite=None), extend or decorate the bundle's subscriber service via services.yaml rather than editing the vendor code:
services:
App\EventListener\RefererCookieListener:
decorates: medelse_referer_cookie.listener
arguments: ['@request_stack']
Testing. In functional tests, drive the subscriber with a synthetic request carrying a Referer header and assert the Set-Cookie on the response, or assert the cookie value on the follow-up request via the kernel browser.
Referer header is frequently absent. Direct traffic, bookmarks, HTTPS→HTTP navigations, and any site that sets Referrer-Policy: no-referrer or strict-origin will send nothing or only the origin. Always handle the null case explicitly and decide whether "no referer" means direct or unknown.strict-origin-when-cross-origin); you will often get https://partner.example/ without the path. Do not design downstream logic that depends on the full path.SameSite and HttpOnly — marketing/analytics needs often require reading the value in JS, which conflicts with HttpOnly.kernel.request listener that redirects (e.g. locale detection), ensure the referer cookie is set before the redirect, or the first-hit value is lost.Referer header exists at all, then inspect the Set-Cookie in the Response panel. If the cookie appears but won't persist, the issue is almost always domain/path mismatch or SameSite blocking a POST cross-origin flow — not the bundle.config/bundles.php silently leaves the subscriber unloaded and you'll chase a "cookie never set" bug for hours.CaptureReferer middleware, apply it to a web group, and use Cookie::queue() with a 30-day lifetime; read it with $request->cookie('referer'). This reproduces the package's entire behaviour in a framework you can maintain.How can I help you explore Laravel packages today?