Skip to content

Only write the fbp and fbc cookies when there is a pixel to send to - #50

Merged
loevgaard merged 1 commit into
masterfrom
fix/28-fbp-cookie
Sep 14, 2026
Merged

loevgaard merged 1 commit into
masterfrom
fix/28-fbp-cookie

Conversation

@loevgaard

@loevgaard loevgaard commented Sep 7, 2026

Copy link
Copy Markdown
Member

Fixes #28

Problem

StoreFbpSubscriber and StoreFbcSubscriber wrote their cookies on the response to every main request, including in applications with zero pixels configured. Every Set-Cookie header makes a response uncacheable for Symfony HttpCache, Varnish and CDNs, so this quietly cost cacheability sitewide for something that may not be in use at all. Neither subscriber consulted the pixel provider, unlike AddLibraryToTagBagSubscriber, which already checks getPixels().

The private setCookie() method was a predicate whose name read like a command.

Change

  • Both subscribers skip when the pixel provider returns no pixels: there is nowhere to send events to, so there is nothing to identify the browser for.
  • The cookie names and the 90-day lifetime move into a shared Cookie\Cookies class used by the two contexts that read them and the two subscribers that write them, replacing four magic strings.
  • setCookie() is renamed to shouldSetCookie().

Removed after review

An earlier revision also added cookies.fbp / cookies.fbc switches and skipped writing on 4xx/5xx responses. Both are gone. The switches were speculative configuration with no request behind them, and the status-code guard did not achieve what it claimed — a status code says nothing about whether a response is a cacheable HTML page — while Meta's own parameter builder does no such check. The pixel guard is what actually stops cookies on sites that do not use them.

Tests

StoreFbpSubscriberTest (its first): cookie set, not http-only so the browser pixel can read it, skipped without pixels, without consent and on a sub request, and the two-hour renewal window in both directions. StoreFbcSubscriberTest mirrors it, plus the fbclid presence check and the context returning no value.

Verified on PHP 8.1 and 8.4, with --prefer-lowest and highest.

@codecov

codecov Bot commented Sep 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.73684% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 97.95%. Comparing base (b944058) to head (0fb55dd).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
src/Cookie/Cookies.php 0.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master      #50      +/-   ##
============================================
+ Coverage     90.49%   97.95%   +7.45%     
- Complexity      148      151       +3     
============================================
  Files            31       32       +1     
  Lines           484      488       +4     
============================================
+ Hits            438      478      +40     
+ Misses           46       10      -36     
Files with missing lines Coverage Δ
src/Context/Fbc/CookieBasedFbcContext.php 100.00% <100.00%> (ø)
src/Context/Fbp/CookieBasedFbpContext.php 100.00% <100.00%> (ø)
src/EventSubscriber/StoreFbcSubscriber.php 100.00% <100.00%> (+80.00%) ⬆️
src/EventSubscriber/StoreFbpSubscriber.php 100.00% <100.00%> (+84.00%) ⬆️
src/Cookie/Cookies.php 0.00% <0.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@loevgaard
loevgaard force-pushed the fix/17-pii-in-transport branch from 9a99ee8 to dcbe1cb Compare September 7, 2026 12:03
@loevgaard
loevgaard force-pushed the fix/17-pii-in-transport branch from dcbe1cb to af21153 Compare September 7, 2026 12:18
@loevgaard
loevgaard force-pushed the fix/17-pii-in-transport branch from af21153 to bac5d1e Compare September 7, 2026 12:46
@loevgaard
loevgaard force-pushed the fix/17-pii-in-transport branch from bac5d1e to c9f1d9d Compare September 7, 2026 12:51
@loevgaard
loevgaard force-pushed the fix/17-pii-in-transport branch from c9f1d9d to 5c3470c Compare September 7, 2026 12:57
@loevgaard
loevgaard force-pushed the fix/17-pii-in-transport branch from 5c3470c to 77d1a3e Compare September 14, 2026 07:29
@loevgaard
loevgaard force-pushed the fix/28-fbp-cookie branch 2 times, most recently from 1752b17 to 97ab8f5 Compare September 14, 2026 07:39
@loevgaard
loevgaard force-pushed the fix/17-pii-in-transport branch from 77d1a3e to d13d703 Compare September 14, 2026 07:52
@loevgaard
loevgaard force-pushed the fix/17-pii-in-transport branch from d13d703 to 6857dd6 Compare September 14, 2026 08:07
@loevgaard
loevgaard changed the base branch from fix/17-pii-in-transport to master September 14, 2026 08:26
@loevgaard
loevgaard force-pushed the fix/28-fbp-cookie branch 2 times, most recently from 176bc4b to 749cb00 Compare September 14, 2026 08:33
Comment on lines +69 to +76
->arrayNode('cookies')
->info('The bundle writes the _fbp and _fbc cookies server side. When client side tracking is enabled the browser pixel writes the same cookies, so you may not need these')
->addDefaultsIfNotSet()
->children()
->booleanNode('fbp')->defaultTrue()->end()
->booleanNode('fbc')->defaultTrue()->end()
->end()
->end()

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure we need this?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, and removed. These switches came from my own hedge in the original issue ("consider a config switch") rather than from anything anyone asked for. The case they were meant for — a site where the browser pixel already writes the cookies — does not need them either: the pixel simply overwrites the same cookie name. The pixel guard is what actually matters for sites that don't use cookies at all, and that stays.

The cookies node is now introduced by #51, which only holds domain and lifetime.

Comment thread src/EventSubscriber/StoreFbcSubscriber.php Outdated
@loevgaard loevgaard changed the title Only write the fbp and fbc cookies when they are useful Only write the fbp and fbc cookies when there is a pixel to send to Sep 14, 2026
Both cookies were written on every main-request response, including in
applications with no pixels configured at all, and every Set-Cookie
header makes a response uncacheable for shared caches.

Skip when the pixel provider returns nothing, move the cookie names and
lifetime into a shared Cookies class instead of four magic strings, and
rename the setCookie() predicate to shouldSetCookie().

Fixes #28
@loevgaard
loevgaard merged commit ee105bc into master Sep 14, 2026
44 of 45 checks passed
@loevgaard
loevgaard deleted the fix/28-fbp-cookie branch September 14, 2026 09:25
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.

StoreFbpSubscriber sets the _fbp cookie on every response, also without pixels

1 participant