Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Utm Cookie Bundle Laravel Package

medelse/utm-cookie-bundle

A Symfony bundle that stores UTM campaign parameters in a cookie so attribution data survives across requests and redirects. It captures traffic source details and keeps them available for later tracking, lead attribution, or analytics.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony bundle, not a Laravel package — there is no service provider auto-discovery. If you are working in Laravel, the practical move is to read the bundle's ~100 lines of source and port the listener into a Middleware (see Implementation Patterns). If you are in a Symfony app:

  1. composer require medelse/utm-cookie-bundle
  2. Register it in config/bundles.php:
    Medelse\UtmCookieBundle\MedelseUtmCookieBundle::class => ['all' => true],
    
  3. Inspect DependencyInjection/Configuration.php in vendor/medelse/utm-cookie-bundle to confirm the config alias and options (cookie_name, cookie_lifetime, utm_keys, overwrite are the usual suspects). Add a config/packages/*.yaml block if you need to change the cookie name, TTL, or the list of tracked keys.
  4. First use case: a marketing landing page (?utm_source=newsletter&utm_medium=email&utm_campaign=spring). Hit it in a browser, open DevTools → Application → Cookies, and confirm the UTM values were persisted. Then load a second page without the query string and confirm the cookie is still there — that persistence is the entire value of the package.

Where to look first: the bundle's event subscriber (it hooks kernel.request), because that determines when the cookie is written and whether it overwrites an existing first-touch value.

Implementation Patterns

First-touch vs. last-touch attribution. The single most important decision. The bundle writes when UTM params are present in the query string; whether it clobbers an existing cookie depends on its overwrite behavior/config. Decide explicitly: first-touch (don't overwrite once set) is usually what marketing wants for signup attribution; last-touch is what ad platforms want. Verify the behavior in the listener and, if needed, decorate or replace it.

Reading the cookie server-side for conversion events. On signup, checkout, or lead-form submission, read the cookie from the request and persist it onto your domain entity:

// Symfony controller
$utms = $request->cookies->all();
// filter to your tracked keys, then:
$lead->setUtmSource($utms['utm_source'] ?? null);
$lead->setUtmCampaign($utms['utm_campaign'] ?? null);

Copy the values onto the order/lead at creation time — do not rely on the cookie surviving to fulfillment, because cookie TTLs, Safari ITP, and consent resets will eat it.

Hidden form fields. If forms submit cross-domain or you need attribution on a POST that may not carry the cookie, inject the UTM values into hidden inputs at render time. Cheap and survives more edge cases than the cookie alone.

Laravel port (recommended if you're in Laravel). The package's logic is trivial to reimplement as middleware:

public function handle($request, Closure $next)
{
    $response = $next($request);
    $keys = ['utm_source','utm_medium','utm_campaign','utm_term','utm_content'];
    foreach ($keys as $key) {
        if ($request->filled($key)) {
            $response->cookie($key, $request->query($key), 60 * 24 * 30);
        }
    }
    return $response;
}

This gives you full control over overwrite rules, consent gating, and cookie flags — all things the bundle makes awkward to customize.

Integration with analytics. Pair server-side persistence with a small JS read of document.cookie to forward UTMs into GA4/Matomo on pages that don't re-receive the query string. Keep the key names identical between the bundle config and your JS.

Gotchas and Tips

  • Consent / GDPR. UTM cookies are tracking cookies in most EU interpretations. Writing them unconditionally on kernel.request will put you on the wrong side of ePrivacy. Gate the listener behind your consent manager, or switch to a session-scoped server-side store until consent is granted. The bundle has no built-in consent hook — you'll need to short-circuit the listener yourself.
  • It only writes when params are present. No params on the request means no cookie refresh. If you want a sliding expiration, you must re-set the cookie on later requests yourself.
  • Last release 2021, zero stars, zero dependents. Treat it as a snippet, not a dependency. Expect no Symfony 6/7 compatibility work, no security patches, and no answers to issues. Vendor it (App\Utm\...) or fork it — the maintenance cost of owning 100 lines is lower than the cost of an abandoned bundle in composer.json.
  • Cookie flags. Check SameSite, Secure, and HttpOnly in the emitted Set-Cookie. Defaults from 2021-era Symfony may be laxer than your current policy, and HttpOnly will block the JS-read pattern above.
  • Debugging: curl -i "https://app.test/?utm_source=x" and inspect the Set-Cookie header — faster than fighting browser cache. If the cookie isn't appearing, check that your reverse proxy/CDN isn't stripping query strings, and that the listener is actually registered (bin/console debug:event-dispatcher kernel.request).
  • Extension points: the cleanest customization is decorating the bundle's listener service or overriding its definition in services.yaml. If neither is ergonomic (likely, given the package's age), copy the class into your app namespace — you lose nothing.
  • Don't store more than you need. Five UTM keys plus a referrer fit comfortably; stuffing the full query string risks the 4KB cookie limit and breaks silently.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings