Skip to content

Parse the fbp and fbc cookies the way Meta writes them today - #13

Merged
loevgaard merged 2 commits into
masterfrom
fix/parse-current-fbp-and-fbc-cookies
Sep 7, 2026
Merged

Parse the fbp and fbc cookies the way Meta writes them today#13
loevgaard merged 2 commits into
masterfrom
fix/parse-current-fbp-and-fbc-cookies

Conversation

@loevgaard

Copy link
Copy Markdown
Member

Raised from review feedback on Setono/MetaConversionsApiBundle#39, where the question was why the workaround lived in the bundle instead of here. It should live here.

Problem

Fbc::fromString() and Fbp::fromString() reject two shapes Meta itself writes.

1. Click ids containing - or _. The pattern allowed [a-zA-Z0-9]+, but real fbclid values are base64url:

Fbc::fromString('fb.1.1657051589577.IwZXh0bgNhZW0CMTAAAR-uK_5w'); // threw

2. The trailing appendix segment. Meta's own facebook/capi-param-builder-php, which arrives transitively through facebook/php-business-sdk, writes five segments. Run against the vendored 1.3.1:

$b = new FacebookAds\ParamBuilder();
$b->processRequest('www.example.com', ['fbclid' => 'IwAR1a-b_c'], ['_fbp' => 'fb.1.1657051589577.1088522659']);

// fbc: 'fb.1.1788781160733.IwAR1a-b_c.AQECAQMB'
// fbp: 'fb.1.1657051589577.1088522659.AQEAAQMB'

Both patterns required exactly four segments, so both of those threw.

The consequence differs between the two, and the fbp case is the worse one. A caller reading _fbc typically ends up with no fbc at all. A caller reading _fbp typically falls back to generating a fresh value, so the server keeps inventing a new fbp on every request while the browser has a stable one, and the two sides stop describing the same person. Nothing throws visibly and nothing is logged; the only symptom is a lower Event Match Quality in Events Manager.

Change

  • Fbc accepts [A-Za-z0-9_-]+ for the click id.
  • Both accept an optional trailing [A-Za-z0-9_-]{2,8} segment, matching the two appendix lengths Meta's parameter builder defines (APPENDIX_LENGTH_V1 = 2, APPENDIX_LENGTH_V2 = 8).
  • Fb gains getAppendix() / withAppendix() and both value() implementations append it, so a value read from a cookie is written back byte for byte. Rewriting a cookie into a different shape than the pixel expects would be its own bug. The appendix is not interpreted, only carried.

The appendix survives the immutable setters, since they clone.

Compatibility

A minor release. value() only gains a segment for a value that was parsed with one, so existing four-segment values round-trip exactly as before. One test case moved: fb.1.…MiA_ used to be listed as invalid input and is now valid, which is the point of the change.

Tests

Coverage stays at 100% and Infection stays above the 90 MSI threshold. Added: base64url click ids, both appendix lengths round-tripping through value() for Fbc and Fbp, the appendix surviving withClickId(), withSubdomainIndex() and withRandomNumber(), withAppendix() immutability and removal, and rejection of an empty, too short, too long or illegally charactered appendix. The invalid-input providers now also cover an empty click id and a six-segment value.

After this is released

Setono/MetaConversionsApiBundle#39 can drop the parser it currently duplicates and go back to calling Fbc::fromString(), and the same bug on its _fbp path gets fixed for free.

fromString() on both value objects rejected two shapes that Meta itself
produces:

- click ids containing - or _, which is what base64url fbclid values
  look like, because the pattern only allowed [a-zA-Z0-9]
- the trailing appendix segment that facebook/capi-param-builder-php and
  the browser pixel append, e.g.
  fb.1.1788781160733.IwAR1a-b_c.AQECAQMB

Both threw InvalidArgumentException, so a caller reading the cookie the
pixel had just written got nothing back. For fbp that is worse than for
fbc: the usual fallback is to generate a new value, so the server side
events stopped matching the browser ones.

Both patterns now accept those shapes, and the appendix is preserved so
a value read from a cookie is written back byte for byte.
Comment thread src/ValueObject/Fbc.php Outdated
@loevgaard
loevgaard merged commit 36270b7 into master Sep 7, 2026
28 checks passed
@loevgaard
loevgaard deleted the fix/parse-current-fbp-and-fbc-cookies branch September 7, 2026 12:34
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.

1 participant