Next.jsconsent testingdevelopers
Laptop and phone displaying desktop and mobile website layouts

How to test cookie consent across page navigation in Next.js

CS
ConsentScope Team
September 28, 202610 min read

If consent works after a hard refresh but fails after an internal link, test the route transition itself. A Next.js application can preserve client state and loaded libraries while its visible page changes. The code that correctly waits on first load may not be the code that sends the next page-view event.

Start with two URLs: a simple entry page and a destination that loads a meaningful integration, such as a video or analytics event. Compare direct entry to the destination with navigation through the app. Do not rewrite the banner until you know which path produces the unexpected behavior.

Use this route test matrix

ScenarioStarting stateObservation to record
Direct entry to /pricingFresh session; no choiceInitial script loads, storage writes and consent defaults
Internal link to /pricingReject on the entry page firstWhether a route event bypasses the saved refusal
Reload /pricingKeep the saved refusalWhether startup restores the same state
Accept analytics, then navigateAnalytics granted; other categories unchangedExpected analytics behavior without granting unrelated categories
Withdraw, then navigate backPreviously accepted sessionWhether an already loaded library continues sending
Open the destination in another tabPersisted choice in the same profileWhether the new tab restores the choice consistently

These are test cases, not measured results for a particular Next.js website. Use real routes from your application and write the expected behavior before running them. If an embed is deliberately click-to-load, include the click as a separate action instead of expecting it to appear during an idle scan.

Separate script scheduling from permission to run

A script loading strategy does not represent a visitor's choice. Moving a tag from beforeInteractive to afterInteractive changes scheduling; it does not create a consent gate. Check the condition that permits initialization and the conditions that permit later event calls.

Next.js documents that onReady can run after loading and again when the component remounts. If your callback initializes tracking, inspect that remount path as well. See the Script component reference. Treat the callback as an entry point to review, not as a fix by itself.

Removing a script element after withdrawal does not undo code that already executed. A library may still have timers, listeners or queued events. Use its supported consent or shutdown behavior where available and verify the next event, not merely whether the script node disappeared from the DOM.

Follow one event through the application

  1. Record the production build identifier, route sequence and saved consent choice. Run the production build on staging when possible; development-only behavior can confuse the comparison.
  2. Keep the network capture across navigation. Note the moment of the route transition and the request you did not expect.
  3. Locate the route-change handler. In App Router code, inspect effects that depend on pathname or search parameters. In Pages Router code, inspect the router event integration actually used by the application.
  4. Check what consent value the handler reads at send time. A value captured earlier in a closure can differ from the current CMP state.
  5. Check whether the same event comes from both an application effect and a tag-manager history trigger. Disable one path on staging to isolate duplication.
  6. Repeat after withdrawal without reloading. Then perform a full reload and compare the two captures.

The usePathname documentation is a reference for observing pathname changes in Client Components. It does not supply consent state. Your CMP integration still needs a reliable way to expose the current choice to whichever code handles those changes.

Check unknown, denied and granted as separate states

An application often starts before its CMP has finished restoring a saved choice. Do not silently turn that unresolved state into granted. Define what may initialize while the state is unknown, what remains blocked when it is denied, and which category permits each integration. Keep the same rules for route events and delayed callbacks.

SymptomCandidate causeTargeted retest
Only internal navigation sends the unwanted eventRoute handler bypasses the consent gateReject, navigate through the exact route, inspect event timing
Two page views after one link clickAutomatic tracking plus a manual handlerKeep only one event path on staging and repeat
Withdrawal works only after reloadLoaded SDK or stale callback still uses the old stateWithdraw and trigger another event without reloading
A returning visitor briefly gets tracking before refusal restoresInitialization races with CMP startupThrottle the test connection and inspect event order
Only one nested route failsRoute-specific embed, layout or integrationCompare direct entry and client navigation to that route

Each row gives a hypothesis. Verify it before changing production. For example, two requests can be different events rather than duplicates; compare their purpose and payload. Conversely, one visible cookie does not mean one integration is installed. Keep the investigation tied to the event you can reproduce.

Attach the route sequence to a developer-ready snapshot

Use Extension Pro to inspect captured requests and export a Debug Snapshot. Add your route steps and consent choices so the next developer can reproduce the same sequence.

Get Pro for consent debugging

What counts as a completed fix?

The previously failing transition must match the documented behavior with no choice, with refusal, with the relevant grant and after withdrawal. Check direct entry too. Fixing a client-side route event must not leave the server-rendered entry path loading the same integration unconditionally.

Write the result next to the build and configuration versions. Keep an explicit inconclusive state for captures where the CMP never loaded or the target request was blocked by the browser. For a reusable release checklist, use cookie consent regression testing; for a broader setup overview, see WordPress and Next.js consent implementation.

Will a scan of the destination URL catch a route-only problem?

Not necessarily. Loading a URL directly is a different test from reaching it through a client-side transition. Scheduled scans can help monitor selected entry pages, but keep an interaction test for the route sequence that previously failed. Do not describe a direct-page scan as full coverage of an SPA journey.

CS

ConsentScope Team

Verified author

ConsentScope product team

We build ConsentScope and write practical guides to inspecting browser storage, consent signals and network activity. Our examples distinguish recorded observations from test scenarios.

Published: September 28, 2026Updated: October 3, 2026

Your cookie choices

Essential cookies support sign-in and security. With your permission, Google Analytics measures website visits using analytics cookies. Rejecting analytics does not limit access. You can change your choice anytime in Cookie settings. Privacy Policy