Hello I am a very experienced web dev who is brand new to Drupal and learning to build my first site in it.

I have a very simple site I am converting from pure code (html, css, jquery, angular, bootstrap, php) to drupal so that I can add a CMS backend to the site. On this site I need to track what ad campaign sent the user to the site to be stored with the users information later after they submit their email to be contacted again.

This is how it works currently on the non-drupal site: User clicks on a link on an 3rd party site that directs them to my-site.com/get-eBook.html?campaign=google. On get-eBook.html there is a menu item for /ebook-register.php, I use some PHP to grab the value of campaign from the URL and if it is not null I update the menu item to /ebook-register.php?campaign=google in order to pass the value along to the register page where it is used in a SQL statement and captured in the DB with the users email address.

Now I'm not sure how to accomplish the same thing in Drupal. I have my theme set up, I have two pages created (get-ebook and ebook-register) and I have my menu set up with the link to ebook-register. I however have no idea how I can grab the value of campaign on the get-ebook page and add that value onto the desired menu item being returned by the drupal core so that the value of campaign will be preserved when the user navigated from get-ebook to ebook-register.

Any ideas on how I can allow the menu to be maintained via the Drupal backend but still have the ability to dynamically add query parameters to the items after they're returned from the core?

  • There are a couple different ways to do this depending on which version of Drupal you are using. For Drupal 7 I would suggest using hook_menu_alter or hook_menu and use wildcards. You can also do this with Views.
    – sareed
    Dec 18, 2014 at 22:26
  • I'd do it in a module with hook_menu as sareed says. Drupal hooks can involve a bit of back and forth for reference. Using a drupal-specific IDE like phpstorm can speed things up in this regard. Dec 19, 2014 at 2:52
  • I'm looking at the hook_menu() documentation and I don't see anything that let's you edit an existing menu item, I just see where you can create new menu items. Dec 19, 2014 at 20:11
  • 1
    You cannot do it in hook menu because the menu returned from hook menu & hook menu alter gets cached (your hooks won't run on every page load).
    – rooby
    Dec 19, 2014 at 20:37
  • That's probably an opinion-based thing, but I'd put the URL parameter in a cookie and then extract the cookie value when it's needed for whatever later.
    – leymannx
    Aug 15, 2019 at 14:57

2 Answers 2


The way I would do this would be overriding the menu link.

You can override a menu link by doing a theme override of theme_menu_link() however you don't want to modify the structure of the markup you want to modify the data being printed (in this case the link query string) so I would recommend overriding the variables of that function in hook_preprocess_HOOK() (in this case hook_preprocess_menu_link()).

Template variable overriding is often done in the theme, and you can do it in your theme's template.php file, however in your case I would recommend a custom module because this is functionality not visual display. If you put it in your theme's template.php and then change themes it will stop working, which is probably not what you want.

So it would be best in a custom module.

If you look back at the docs for theme_menu_link() you can see that the link is created using the l() function and looking at the parameters to the l() function you see that the $options parameter can contain "Additional $options elements used by the url() function", which you can see from the url() docs includes the query string, which is a non-encoded array of key/value pairs.

So from that you can tell that in your theme function preprocessor you need to modify/add your query string in $element['#localized_options']['query'] something like this:

$variables['element']['#localized_options']['query']['campaign'] = 'google';

You can also see that the URL of the link is in $element['#href']. Since you probably want to affect all links that point to that path I would suggest overriding the link options based on path.

Since you can access the current page's query parameters using basic PHP's superglobal $_GET you then have all the information you need to set your menu item.

You can do it like this:

 * Variable preprocessor for the themeing of menu links.
 * @see theme_menu_link().
function MODULENAME_preprocess_menu_link(&$variables) {
  // If we have an ebook campaign code then add it to the ebook register
  // menu link.
  if ($variables['element']['#href'] == 'ebook-register.php' && !empty($_GET['campaign'])) {
    // Just add our query array element instead of setting query to a new
    // array to avoid possibly overwriting other query parameters.
    $variables['element']['#localized_options']['query']['campaign'] = $_GET['campaign'];

One other thing worth nothing is that generally in Drupal you shouldn't have pages as custom PHP scripts like ebook-register.php.

Instead you should have a custom module that implements hook_menu() to make the path 'ebook-register' call a custom callback that then contains your page logic. See the drupal menu system docs for more information (D6 & D7 have the same menu system) and also the examples module's menu & page examples.


Drupal always caching menu and menu items, so you can not have custom menu item for each visitor. Sure you can do it by altering menu link but you will face caching/performance issues with this, because this is like having custom item URL for each visitor.

Performance wise: don't use the scope you are talking about try to reach the final result with another way.

I suggest to re-think about how you do this to get the final result. I mean think to save campaign name in the user cookies (client-side) or user session at first page view instead of have this in the URL and move the value to all internal URLs. So, you will save the value in cookie from URL at first time. You can save the value by cookie using jQuery for example, and get the value in server side when submitting form.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.