Shortcodes in Menus — For A Better Staging

A shortcut by a hairdresser

Main­tain­ing a Word­Press-based site often means work­ing with two instances — one for devel­op­ment and one for pro­duc­tion. Both have their own domain, a spe­cif­ic URL, used to link one site ele­ment to anoth­er. Man­u­al­ly or auto­mat­i­cal­ly. This implies that a web design­er has to replace this URL pre­fix with the oth­er one in all places if she wants to bring test­ed pages into pro­duc­tion. She can trig­ger this replace­ment in dif­fer­ent ways, man­u­al­ly or with a replace­ment plu­g­in. Here, we describe short­codes in menus — anoth­er method that sim­pli­fies such work sig­nif­i­cant­ly.

[ en | de ]


  • Install the plu­g­in Shortcode in Menus.
  • Add the fol­low­ing lines to your functions.php:
 * (c) 2023, Karsten Reincke
 * SPDX-License-Identifier: MIT
 * following some ideas of
 * https://wordpress.org/support/topic/how-does-it-work-24/page/2/#post-4987738

function myDomain_shortcode($atts) {
  return get_site_url();
add_shortcode ( 'myDomain', 'myDomain_shortcode' );
  • In the future, use insert the string [­myDomain]/myElement in the link dia­log of a page or post if you want to link it to myElement.


There are sev­er­al meth­ods to replace the URL of the devel­op­ment sys­tem with the oth­er URL of and for the pro­duc­tion sys­tem, good and bad. Among the good ones, a spe­cial chap­ter “Switch the domain name to the pro­duc­tion name” rec­om­mends the plu­g­in Go Live Update URLs. That plu­g­in does what the com­mand cat mydevdump.sql | sed "s/http:\/\/devdomain/https:\/\/proddomain/g" > myprodump.sql would also do — with oth­er means. Like the plu­g­in Bet­ter Search Replace.

But the chal­lenge is that you have to do the same thing over and over again. Every time, you want to migrate some­thing from devel­op­ment into pro­duc­tion. The method pro­posed here is eas­i­er and more sus­tain­able. It assumes …

  • we have a devel­op­ment machine where we work on mul­ti­ple Word­Press instances.
  • our devel­op­ment instances reside in the HTTP root as a devel­op­ment fold­er.1
  • we have defined the Word­Press address and site of each of our devel­op­ment instances in the Word­Press set­tings as
  • for each devel­op­ment instance, there is a pro­duc­tion instance with a dif­fer­ent Word­Press and site address.

Until now, when cre­at­ing a menu item, Word­Press com­plet­ed what we entered into a menu item by that what we had defined in the set­tings. It com­plet­ed it direct­ly. Sta­t­i­cal­ly. Now we want this to hap­pen every time the ele­ment is called. Not sta­t­i­cal­ly, but dynam­i­cal­ly. To enable that, we replace the fixed URL pre­fix of a link to a page or post with a short­code. And the func­tion asso­ci­at­ed with that short­code gets the cur­rent val­ue using get_site_url() and replaces our short­code accord­ing­ly.

How­ev­er, that method needs the help of the plu­g­in Short­code in Menus which ensures that short­codes are also eval­u­at­ed in ele­ments where Word­Press expects URLs: Because how should Word­Press know with­out sup­port that a cer­tain string is not a gen­uine part of the URL? For­tu­nate­ly, unlike the plu­g­in name would lead you to expect, this method also works in URLs out­side the menu.

And so we can now write our posts and pages on the devel­op­ment envi­ron­ment and push them direct­ly into the pro­duc­tion — with­out hav­ing to replace the devel­op­ment URLs before migrat­ing them.2

What a pity …

Unfor­tu­nate­ly, the solu­tion described here does not work for man­u­al­ly set inter­nal links point­ing to site pages. This is because Guten­berg’s link­ing dia­log pre­fix­es entries with a pro­to­col (https://, http:/, …) if Guten­berg missed pro­to­col infor­ma­tion. That’s bad if the Short­Code [­myDo­main] — as sug­gest­ed here — is resolved by any­thing like https://wherever.de/. The first solu­tion for this issue requires addi­tion­al typ­ing work: we would define [­myDo­main] as a pure domain and man­u­al­ly prepend the pro­to­col to each menu entry and inter­nal link cre­at­ed by the link­ing dia­log. The sec­ond solu­tion has a taint: We would define the Short­Code [­myDo­main] as described above, pre­vent our­selves from using it in the link­ing dia­log, and take what Word­Press offers us auto­mat­i­cal­ly. But then — after hav­ing migrat­ed an arti­cle from devel­op­ment to pro­duc­tion — we would have to replace each devel­op­ment URL with the pro­duc­tion URL by the plu­g­in Bet­ter-Search-Replace or sim­i­lar.

What shall you do? No idea. I am going to take the dis­ap­point­ing solu­tion and save myself some typ­ing work.

And how does this … Menu

… sup­port our migra­tion to bootScore? Well, once a web design­er has tak­en the first gen­er­al steps and has checked SEO, she will soon turn to a real­ly thick board, her prop­er­ly clus­tered and pre­sent­ed menu with­out get­ting too fan­cy. Even­tu­al­ly, she is going to spruce and speed up the dis­play of fixed and scal­able images. This post talks about a part of this way.

  1. So the instance is devel­oped at the URL — or what­ev­er myDevDir is called in real terms. []
  2. But if you want it even more sim­ple, you can work with basic-url-short­codes. []
To top