Summary: Define dynamic URL trails
Version: 2.2 - 24 March 2007)
Prerequisites: Last tested on PmWiki version: 2.2.0-beta35
Maintainer: Martin Fick, JamesM


  1. How can I make a page be a part of multiple trails?
  2. How can I make pages be a part of trail without having to put trail markup on every page in the trail?


Define dynamic URL trails with this recipe:

Note: For question # 2 you will need to use the Group Header/Footer Trail markup mentioned near the end.

PmWiki Versions prior to 2.2.0 Add this markup and condition to your config.php

  Markup('{$Trail}','>{$fmt}',  '/{\\$(Trail)}/e',  "\$_REQUEST['$1']"); 
  $Conditions['trail'] = "isset(\$_REQUEST['Trail'])"; 

  Markup('(:trailindex:)','directives',  '/\(:trailindex:\)/e', "addtrail()"); 
  function addtrail() { global $AddTrail; $AddTrail = TRUE; return ""; } 

PmWiki Versions 2.2.0 and later Add this markup and condition to your config.php

  $FmtPV['$Trail'] = "\$_REQUEST['Trail']"; 
  $Conditions['trail'] = "isset(\$_REQUEST['Trail'])"; 

  Markup('(:trailindex:)','directives',  '/\(:trailindex:\)/e', "addtrail()"); 
  function addtrail() { global $AddTrail; $AddTrail = TRUE; return ""; } 

All known PmWiki versions Patch your pmwiki.php (carefull!)

To the LinkPage() function:

  • Add $AddTrail to the globals:
function LinkPage($pagename,$imap,$path,$title,$txt,$fmt=NULL) {
     global $QueryFragPattern,$LinkPageExistsFmt,$LinkPageSelfFmt,
  • Toward the end of the function, add this line:
if ($AddTrail) $qf .= $qf ? "&":"?" . "Trail=$pagename";
     $fmt = str_replace(array('$LinkUrl', '$LinkText'),
             array(PageVar($tgtname, '$PageUrl').PUE($qf), $txt), $fmt);
     return FmtPageName($fmt,$tgtname);

To the MarkupToHtml() function:

  • Add $AddTrail to the globals and then add the next line:
   function MarkupToHTML($pagename, $text, $opt = NULL) {
    # convert wiki markup text to HTML output
    global $MarkupRules, $MarkupFrame, $MarkupFrameBase, $WikiWordCount,
    $K0, $K1, $RedoMarkupLine, $AddTrail;

    $AddTrail = FALSE;

Seed your wiki trail on the trail index page with the new (:trailindex:) directive


  * [[Group.Page1]] 
  * [[Group.Page2]] 
  * [[Group.Page3]] 

This will make every link to a page have the following arguments inconspiculously added to them:


Define a Pagelist Template with your wiki trail markup.

  • Note, for PmWiki versions prior to 2.2.0-beta1, remove the * in the {*$FullName} and {*$Trail} syntax.
  • in PmWiki versions since 2.1.x, you should add these to the Site.LocalTemplates page.

This template simulates the regular trail markup

(:if equal {*$FullName} {=$FullName} :)
<[[{<$FullName}?Trail={$$trail}|{<$FullName}]] |\
 [[{$$trail}]] |\


This template uses page titles instead of pagenames

(:if equal {*$FullName} {=$FullName} :)
<[[{<$FullName}?Trail={$$trail}|{<$Title}]] |\
 [[{$$trail}|{{$$trail}$Title}]] |\


This template can be used in a sidebar to show the current trail index along
with the current page highlighted in the sidebar. Can also be used to simply
list a trail contents for a specific trail.  

(:if equal {<$FullName}:)
! [[{$$trail}|{{$$trail}$Title}]]
(:if ! equal {*$FullName} {=$FullName} :)
* [[{=$FullName}?Trail={$$trail}|{=$Title}]]
(:if equal {*$FullName} {=$FullName} :)
* [[{=$FullName}?Trail={$$trail}|'''{=$Title}''']]

Define a Dynamic Trail Markup on Pages in the Trail

The dynamic trail markup can look like this:

   (:if trail:)(:pagelist trail={*$Trail} fmt=<templatepage>#trail:)(:if:) 

where <templatepage> refers to the page where you defined your trail markup in the previous step, or leave it blank if you used Site.LocalTemplates.

  • Note for PmWiki versions prior to 2.2.0-beta1, remove the *.
  • This trail markup will only render if the viewer is actually navigating a dynamic trail and it will reflect the appropriate trail. No need to define which trails the page might possibly be in.
  • to make things even simpler you could put this markup in a Group Header or Footer without affecting pages that are not a part of a trail. This markup should even be safe if you use the AllGroupHeader recipe to make it global to the site.

You can also specify a trail to list the index for like this:

   (:if trail:)(:pagelist trail=Group.PageName fmt=<templatepage>#trail:)(:if:) 

Version History

  • Version 2.2 (3/24/2007) updated for PmWiki 2.2.0-beta1 and later
    • use FmtPV[] instead of Markup() - Kudos to CommentPageLink
    • change {$Trail} to {$$trail} (case sensitive) in PageList Templates for PmWiki 2.1.x where {$$Option}} pagelist variables were enabled
    • add * to all {$Trail} references for PmWiki 2.2.0-beta1 where * denotes rendering context
  • Version 2.1 (6/20/2006) makes use of qf as Kathryn Andersen suggested
  • Version 2 (6/1/2006) adds (:trailindex:) to seed the trail and uses a pagelist to create the trail markup
  • Version 1 required manually adding ?Trail=<trailindexpage> to every page on the trail


  • The {*$Trail} markup makes {*$Trail} render as <value> from ?Trail=<value> urls
  • The (:trailindex:) directive adds ?Trail=<trailindexpage> to all pagelinks on this page
  • The condition allows testing for the presence of a trail url
  • The addtrail() function is used by the (:trailindex:) directive
  • The patch to LinkPage() adds the trail arguments to each page link for (:trailindex:)
  • The patch to MarkupToHtml() turns off the (:trailindex:) so that it does not affect the sidebar
  • The default {$$option} processing now maps trail=<trailindexpage> to {$$trail} for pagelists


  • For a working example try these two overlapping trails: Trail1and Trail2 (old version on PmWiki 2.1.6)

See Also



See discussion at DynamicWikiTrails-Talk

User notes? : If you use, used or reviewed this recipe, you can add your name. These statistics appear in the Cookbook listings and will help newcomers browsing through the wiki.