WordPress wp_get_nav_menu_items Example: Fetch Menu Data for Headless Output
Fetch WordPress menu items cleanly with wp_get_nav_menu_items() and map navigation data for a headless frontend.
Published
May 4, 2026
Reading Time
2 min read
Updated
May 4, 2026

Implementation Notes
Extension points, code paths, and implementation choices that should survive contact with production.
Best For
WordPress developers, agencies, and technical teams building custom plugin or theme functionality with cleaner operational defaults.
Primary Topics
Editorial Focus
Build Pattern: Extension points, code paths, and implementation choices that should survive contact with production. Updated on May 4, 2026.
Full Report
Last reviewed: May 4, 2026
Headless WordPress frontends eventually need navigation data that is structured, predictable, and not tied to theme rendering. wp_get_nav_menu_items() is the core helper for retrieving menu items from a classic menu so code can transform them into a clean array or JSON response.
This guide shows how to fetch menu items safely, how to resolve the right menu from a theme location, and why output mapping should be explicit before a frontend consumes the data.
Resolve the assigned menu from a location first
<?php
$locations = get_nav_menu_locations();
$menu_id = $locations['primary'] ?? 0;
if ( ! $menu_id ) {
return array();
}
$items = wp_get_nav_menu_items( $menu_id );
This avoids hardcoding a menu term ID into plugin or theme logic. The location assignment stays the source of truth.
Map the returned objects into a front-end-safe structure
<?php
$links = array();
foreach ( $items ?: array() as $item ) {
$links[] = array(
'id' => (int) $item->ID,
'parent' => (int) $item->menu_item_parent,
'label' => wp_strip_all_tags( $item->title ),
'url' => esc_url_raw( $item->url ),
);
}
return $links;
The returned menu item objects contain more data than many frontends need. Mapping them deliberately keeps the contract narrow and easier to reason about.
Do not assume a menu always exists
The function can return false if the menu does not exist. Production code should treat missing navigation as a real state and return an empty array or a fallback object instead of throwing warnings into logs.
Keep menu output separate from page rendering assumptions
Classic theme helpers often jump directly from menu configuration to HTML. Headless systems should separate retrieval from presentation so the frontend can decide how to render depth, active states, and responsive behavior.
Common mistakes
- Hardcoding a menu ID. Theme locations are the safer integration point.
- Passing raw menu item objects straight to the frontend. Explicit mapping makes API contracts cleaner.
- Skipping empty-state handling. Missing menu assignments happen in real environments.
- Mixing retrieval logic with HTML rendering concerns. Headless systems benefit from a narrower data layer.
Production checklist
- Resolve the menu through a named location when possible.
- Map only the fields the frontend actually needs.
- Handle the no-menu case without PHP warnings.
- Normalize IDs, parent links, labels, and URLs before returning data.
- Test nested items if the frontend supports multilevel navigation.
Related reading
Pair this with the Walker Nav Menu article when a classic theme still renders the HTML, and with the register_rest_route guide if the menu data will be served through a custom API layer.


