🐞 fix(nextjs): Fix Next.js server page context/state handoff for query-parameters#339
Open
Charles Hudson (phobetron) wants to merge 1 commit into
Open
🐞 fix(nextjs): Fix Next.js server page context/state handoff for query-parameters#339Charles Hudson (phobetron) wants to merge 1 commit into
Charles Hudson (phobetron) wants to merge 1 commit into
Conversation
…y-parameters ### Summary This fixes server-side audience matching for rules that depend on URL query parameters. The supported Next.js server optimization path can now populate `context.page` from the current request URL, including query parameters, so a request such as `/?test=true` can evaluate query-based audience rules instead of silently rendering baseline content. While investigating the bug, the issue turned out to span more than URL parsing. Next.js App Router splits request handling, Server Component rendering, and browser startup across different boundaries. The previous request-handler API mixed request context capture, `page()` execution, consent resolution, and cookie persistence in middleware/proxy code, which made it hard for Server Components to reliably receive page URL context without duplicating work. This PR separates those responsibilities and documents the supported integration paths. ### What changed - Added shared page-context creation in Core so request URLs are normalized into SDK-compatible `page.path`, `page.search`, `page.query`, `page.referrer`, and `page.url`. - Updated the Next.js server helpers to derive page context from: - direct request objects, - sanitized proxy/middleware-forwarded request URL headers, - explicit App Router route state via `createNextjsPageContext()`. - Replaced the page-producing Next.js request handler with `createNextjsOptimizationContextHandler()`, which only forwards sanitized request context for Server Components. - Added `@contentful/optimization-nextjs/esr` for edge/request-rendered flows that own both the incoming `Request` and outgoing `Response`, including anonymous ID persistence. - Added explicit server-to-browser Optimization state handoff through: - `serverOptimizationState` on React Web provider/root APIs, - `NextjsOptimizationState` for shared App Router layouts where page data is produced below the provider. - Introduced internal first-party `bridge-support` entry points for controlled state hydration and preview-panel access, replacing public symbol/register-preview wiring. - Added diagnostics for conflicting explicit page context versus page event properties. - Updated Next.js SSR and hybrid reference implementations to use the new request-context and state-handoff model. - Updated package READMEs, Next.js integration guides, and related concepts for consent, profile synchronization, locale handling, and server/stateless interaction tracking. ### Why the scope expanded A narrow fix that only parsed query strings would not have made the supported Next.js App Router flow reliable. Server Components do not naturally receive the full request URL, and the old middleware helper tried to solve that by performing SDK work at the request layer. That created unclear ownership over consent, page events, cookie persistence, and browser handoff. This PR makes the boundaries explicit: - proxy/middleware captures request URL context only; - Server Components own `getNextjsServerOptimizationData()` and the initial server `page()` call; - ESR helpers own request/response-based rendering flows; - React/Next client code receives server-returned Optimization data through an explicit handoff API; - preview and state hydration use internal bridge support instead of consumer-visible Core internals. ### Test coverage added or updated - Core stateless page-event tests cover forwarding request page query context. - EventBuilder tests cover `context.page` construction and explicit page-context precedence. - Core bridge tests cover first-party bridge access and Optimization data hydration. - Next.js server tests cover forwarded request URL headers, explicit page options, App Router `searchParams`, and duplicate query value normalization. - Next.js request-handler tests cover sanitized context forwarding and existing-response preservation. - Next.js ESR tests cover plain `Request`, `NextRequest`, cookie reads, cookie persistence, and persistence cleanup. - React Web provider tests cover server Optimization state being applied before `onStatesReady` and before children render. - Next.js client tests cover `NextjsOptimizationState` hydration behavior. [[NT-3568](https://contentful.atlassian.net/browse/NT-3568)]
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.
Summary
This fixes server-side audience matching for rules that depend on URL query parameters. The supported Next.js server optimization path can now populate
context.pagefrom the current request URL, including query parameters, so a request such as/?test=truecan evaluate query-based audience rules instead of silently rendering baseline content.While investigating the bug, the issue turned out to span more than URL parsing. Next.js App Router splits request handling, Server Component rendering, and browser startup across different boundaries. The previous request-handler API mixed request context capture,
page()execution, consent resolution, and cookie persistence in middleware/proxy code, which made it hard for Server Components to reliably receive page URL context without duplicating work. This PR separates those responsibilities and documents the supported integration paths.What changed
page.path,page.search,page.query,page.referrer, andpage.url.createNextjsPageContext().createNextjsOptimizationContextHandler(), which only forwards sanitized request context for Server Components.@contentful/optimization-nextjs/esrfor edge/request-rendered flows that own both the incomingRequestand outgoingResponse, including anonymous ID persistence.serverOptimizationStateon React Web provider/root APIs,NextjsOptimizationStatefor shared App Router layouts where page data is produced below the provider.bridge-supportentry points for controlled state hydration and preview-panel access, replacing public symbol/register-preview wiring.Why the scope expanded
A narrow fix that only parsed query strings would not have made the supported Next.js App Router flow reliable. Server Components do not naturally receive the full request URL, and the old middleware helper tried to solve that by performing SDK work at the request layer. That created unclear ownership over consent, page events, cookie persistence, and browser handoff.
This PR makes the boundaries explicit:
getNextjsServerOptimizationData()and the initial serverpage()call;Test coverage added or updated
context.pageconstruction and explicit page-context precedence.searchParams, and duplicate query value normalization.Request,NextRequest, cookie reads, cookie persistence, and persistence cleanup.onStatesReadyand before children render.NextjsOptimizationStatehydration behavior.[NT-3568]