Headless WordPress menus: what to check before launch

Illustrated infographic summarizing: WordPress headless menus need an exposure check before launch

By Greg Nowak. Updated 1 September 2026.

A headless WordPress site should not need hard-coded navigation. If editors manage the pages in WordPress, letting them manage the primary and footer menus there usually makes sense too.

But once navigation is delivered as JSON, it becomes part of your public application contract. Menu labels, URLs and hierarchy can reveal planned services, campaign pages, account routes, partner areas or internal terminology—even when the linked pages themselves remain protected.

This does not make public menus inherently dangerous. It means the agency or delivery team should decide what is public, test that decision anonymously and record it before launch.

What changed in WordPress 6.8?

WordPress 6.8 introduced the rest_menu_read_access filter. The hook remains in the current WordPress developer reference and applies to the controllers for menus, menu items and menu locations.

By default, these resources are not available for anonymous reading. A developer can opt in and can use the request and controller passed to the filter to grant access selectively. This broad example from the WordPress developer note exposes all three menu-related resources:

add_filter( 'rest_menu_read_access', '__return_true' );

That line is convenient, but it is a policy decision disguised as a small implementation detail. Use it only when every menu resource and its public fields have been reviewed and are genuinely intended for anonymous access.

Start with the front end’s actual data requirement

Map the requests the production application makes. A typical front end may first resolve a location such as primary, obtain its menu ID and then request the associated items. Exposing only the location endpoint may therefore be too narrow, while exposing every menu and every item may be unnecessarily broad.

The right rule follows the fetch sequence. Identify the locations the application needs, the item collection it reads and any fields added by plugins or custom code. Then implement conditional logic in rest_menu_read_access around those specific requests. Keep that logic in a small custom or must-use plugin so it is not silently lost when the theme changes.

Launch decision What to verify Expected evidence
Public routes Menus, items and locations required by the production front end An explicit route list, not “the REST API is open”
Public content Labels, URLs, hierarchy, descriptions, metadata and custom fields A reviewed anonymous JSON response
Failure behaviour Restricted routes and unapproved menu IDs A repeatable 401 or 403 response
Browser access Production, preview and old development origins A documented CORS decision
Cache lifecycle CDN, host, application and framework caches Known TTLs and a tested purge path
Ownership Who approves new locations, fields and integrations A named owner and deployment note
A focused acceptance checklist for public menu data in a headless WordPress launch.

Test as an outsider, not as an administrator

Run the launch checks without WordPress cookies, authorization headers or preview credentials. Replace the host and menu ID below with production-like values:

curl -i https://cms.example.com/wp-json/wp/v2/menu-locations/primary
curl -i 'https://cms.example.com/wp-json/wp/v2/menu-items?menus=MENU_ID&context=view'
curl -i https://cms.example.com/wp-json/wp/v2/menus

Record the status code, response headers and body. Approved requests should return only content the business is comfortable publishing. Unapproved collections, locations and IDs should remain inaccessible. Repeat the tests against the real production configuration because hosting rules, plugins and deployment variables can differ from staging.

WordPress also supports the global _fields parameter, which lets the front end request a smaller response. For example, it can ask only for the item fields it renders. This improves payload size and makes the consumer’s needs clearer, but it is not access control: another caller can omit _fields. Review the complete anonymous response, not only the front end’s preferred query.

Review the menu as publishable content

A technical permission check is only half the job. Ask the content or operations owner to inspect the returned navigation shortly before launch. Look for staging domains, placeholder links, unpublished campaign names, obsolete support routes and internal descriptions. Check plugin-added metadata as carefully as the visible label.

Also test edits. Remove or rename a harmless item, publish the change and measure how long the old JSON survives. Navigation may be cached by WordPress, the host, a CDN, the front-end framework or several layers at once. The team needs a practical purge method before an urgent correction is required.

CORS does not make public menu data private

WordPress intentionally allows public REST endpoints to be accessed from any site by default; its REST documentation explains that WordPress relies on nonces for CSRF protection rather than strict origin verification. CORS mainly controls which browser scripts can read a cross-origin response. It does not stop direct requests, server-side clients or command-line tools.

Review CORS because overly broad or stale configuration is still poor operational hygiene, but do not use it as the confidentiality boundary for menu data. If navigation truly must remain private, keep the endpoint authenticated and fetch it through a trusted server-side component. Never place an Application Password or another reusable secret in browser JavaScript.

Leave the next team a clear rule

The most useful handover is short and testable: which menu locations are public, which routes support them, who may change the policy, how anonymous access is tested and how cached responses are purged. That turns a one-line filter into an owned part of the system rather than launch-day folklore.

If your agency needs an independent pair of eyes, Greg can review the anonymous REST surface, menu contents, cache path and deployment notes without turning the exercise into a heavyweight security programme. Talk to Greg about a practical pre-launch review.

Related on GrN.dk

Need help with this kind of work?

Plan a pre-launch review with Greg Get in touch with Greg.

Sources

Seneste artikler

Sådan automatiserer danske virksomheder Gmail og Microsoft 365 med hurtig sortering, begrænsede rettigheder og menneskelig godkendelse.

Samme kunde på flere kort i HubSpot? Se, hvordan CVR-match, AI-forslag og menneskelig godkendelse kan bruges til at rydde op med styr på felter, relationer og kundehistorik.

Få en ugentlig marketingrapport fra GA4 og Google Ads med kontrollerede beregninger, tydelige dataforbehold og et kort AI-udkast, der hjælper jer på mandagsmødet.

Brug AI til webshoppens alt-tekster med en overskuelig pilot: kortlæg billederne, få danske forslag, og kontrollér resultatet i WordPress og WooCommerce.

AI-baseret ticketanalyse kan afsløre gentagne klager, produktfejl og huller i dokumentationen – uden at virksomheden behøver endnu en chatbot.

OpenSSH 10 fjerner DSA og advarer om nøgleudveksling, der ikke er post-kvantesikker. Her får du en metode til at afgrænse SFTP-oprydningen uden at svække alle SSH-forbindelser.

Botforespørgsler overstiger nu menneskelig webtrafik. Lær at auditere AI-crawlere, fastsætte regler på stiniveau, håndhæve robots.txt og måle det forretningsmæssige afkast.

Cloudflares Tunnel-opdateringer fra 2026 forbedrer kortlægning, overvågning af replikaer, logstreaming og overdragelse – men synliggør samtidig svagt ejerskab og mangelfuld praksis for failover og logging.

Sådan bruger du AI til mødenoter og opfølgning, mens faste regler beskytter CRM-data, kundematch og pipeline mod fejl og forhastede ændringer.

Drupal 10 når end of life den 9. december 2026. Brug denne praktiske kortlægning til at afgrænse arbejdet med Drupal 11-parathed, Composer-efterslæb, moduler og custom code.