Parse the fbp and fbc cookies the way Meta writes them today - #13
Merged
Conversation
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.
loevgaard
commented
Sep 7, 2026
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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()andFbp::fromString()reject two shapes Meta itself writes.1. Click ids containing
-or_. The pattern allowed[a-zA-Z0-9]+, but realfbclidvalues are base64url:2. The trailing appendix segment. Meta's own
facebook/capi-param-builder-php, which arrives transitively throughfacebook/php-business-sdk, writes five segments. Run against the vendored 1.3.1:Both patterns required exactly four segments, so both of those threw.
The consequence differs between the two, and the
fbpcase is the worse one. A caller reading_fbctypically ends up with nofbcat all. A caller reading_fbptypically 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
Fbcaccepts[A-Za-z0-9_-]+for the click id.[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).FbgainsgetAppendix()/withAppendix()and bothvalue()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()forFbcandFbp, the appendix survivingwithClickId(),withSubdomainIndex()andwithRandomNumber(),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_fbppath gets fixed for free.