wp_create_menu_item: create a menu item
Adds an item to a navigation menu.
Arguments
| Argument | Required | Meaning |
|---|---|---|
menu_id |
Yes | The menu to add to |
title |
Yes | The label visitors see |
url |
Yes | Where it points |
parent |
No | Parent item ID; omit for top level |
object / object_id |
No | Link to a WordPress object instead of a URL |
dry_run |
No | Report without creating |
Permissions
Allow content writes open, and edit_theme_options.
It creates a custom link by default
Passing only title and url produces a custom menu item: a literal URL that WordPress does not maintain.
If the page it points at later changes its slug, the menu item silently breaks. Nothing warns you, and it will keep pointing at a URL that 404s.
To create a maintained link instead, pass object and object_id together — for example object: page with the page's ID. WordPress then keeps the URL correct as the target changes.
Prefer the object form whenever you are linking to something on the site. It is the difference between a menu that survives content work and one that quietly rots.
Specify the parent, or it goes to the top level
Omitting parent places the item at the top of the menu — in the main navigation bar rather than inside a dropdown.
That is rarely what is wanted when adding, say, a service page that belongs under Services. Read the menu first, find the intended parent's ID, and pass it.
Show me the items in menu 3 with their IDs and parents. Then add "Maintenance" under "Services".
Position
New items go to the end of their level. To place one elsewhere, create it and then set the order explicitly with wp_reorder_menu_items.
Check the target exists and is public
Nothing validates the URL or the object. An item can be created pointing at:
- a draft page, which visitors cannot see;
- a deleted post;
- a URL with a typo;
- an external site.
All four are created without complaint. Confirm the target before adding it, and open the link after.
The dry run
Reports what it would create, without creating it. Useful for confirming the parent and the target resolved as intended.
After creating
Menus appear on every page, so verification is quick and worth doing every time:
- Open the site and look at the menu.
- Check the item is at the right level, in the right dropdown.
- Click it.
- Check it on mobile, where the menu often renders differently.
- Purge the cache.
Multilingual sites
Each language has its own menu. Adding an item to one adds it to that language only, and a menu that is complete in Spanish and missing an entry in English is a common and confusing result.
Plan the equivalent addition in each language's menu.
Common problems
| Symptom | Cause |
|---|---|
| The write is refused | Content write gate closed |
pom_ai_mcp_forbidden |
No edit_theme_options |
| The item is in the main bar, not a dropdown | parent was omitted |
| The link breaks later | It was created as a custom URL rather than an object link |
| It points at something invisible | The target is a draft |
| It does not appear at all | The menu is not assigned to a theme location |
| Only one language has it | Menus are per-language |
Related
wp_get_menu_items— read the structure firstwp_reorder_menu_items- Edit a navigation menu