I'm new to creating module in Drupal 7 and wondering what hook to use to execute a PHP script.

I use this tutorial but it it explain a different approach.

What I want is simply execute this code in every page:

        'id' => NULL,
        'length' => $t,
        'url' => $url,
        'current_ip' => $current_ip,
        'user_agent' => $user_agent,
        'date_start' => date("Y-m-d H:i:s"),
        'is_bot' => $isbot,
        'is_logout' => 0,

Note that I have already created .module and .info file. All I need is to know what hook to put the code above.

Thanks for any help.

2 Answers 2


I would look into hook_init() if you don't require this to be run on cached pages, hook_boot() if you do.

  • Thanks for the reply. If I run it on hook_boot(), the script will not insert the data into the database because of caching? Is this what you mean? If I need to run the insert command (sql), I have to use hook_init(), right?
    – jaypabs
    Aug 5, 2013 at 14:20
  • no, I mean if you have page caching turned on for anonymous users, then hook_init() won't be run because drupal will just fetch the already rendered html out of its page cache. if you need to have code run in such situations (and aren't using an external cache like Varnish) then you need to have this code in hook_boot().
    – Jimajamma
    Aug 5, 2013 at 14:48
  • Thank you. I don't know what happen but the script does not insert the correct value. Instead inserting user agent, ip address, and url what it insert is the variable name like $current_ip, $user_agent, $url. Here's my code link
    – jaypabs
    Aug 5, 2013 at 14:59
  • 1
    not so sound rude or abrupt, but at this point, this sounds now like a php coding issue, so you'll just have to look at the db_insert() api etc and track down what little bug you have.
    – Jimajamma
    Aug 5, 2013 at 15:13
  • The code works fine when I hard coded it in my theme. Just wondering why it is not working on module. Can you please help me?
    – jaypabs
    Aug 5, 2013 at 15:16

Since you want to write in the database, I would do what the Statistics module that comes with Drupal does.

function statistics_exit() {
  global $user;

  // When serving cached pages with the 'page_cache_without_database'
  // configuration, system variables need to be loaded. This is a major
  // performance decrease for non-database page caches, but with Statistics
  // module, it is likely to also have 'statistics_enable_access_log' enabled,
  // in which case we need to bootstrap to the session phase anyway.

  if (variable_get('statistics_count_content_views', 0)) {
    // We are counting content views.
    if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == NULL) {
      // A node has been viewed, so update the node's counters.
      db_merge('node_counter')->key(array('nid' => arg(1)))->fields(array(
        'daycount' => 1,
        'totalcount' => 1,
        'timestamp' => REQUEST_TIME,
      ))->expression('daycount', 'daycount + 1')->expression('totalcount', 'totalcount + 1')->execute();
  if (variable_get('statistics_enable_access_log', 0)) {

    // For anonymous users unicode.inc will not have been loaded.
    include_once DRUPAL_ROOT . '/includes/unicode.inc';
    // Log this page access.
      'title' => truncate_utf8(strip_tags(drupal_get_title()), 255),
      'path' => truncate_utf8($_GET['q'], 255),
      'url' => isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '',
      'hostname' => ip_address(),
      'uid' => $user->uid,
      'sid' => session_id(),
      'timer' => (int) timer_read('page'),
      'timestamp' => REQUEST_TIME,

hooK_boot() is invoked Drupal has not yet completed its bootstrap. That means, for example that not all the module functions are not available. As for the Drupal functions, not all the functions are available, since some include files are loaded when Drupal completes its bootstrap. See _drupal_bootstrap_full().

  require_once DRUPAL_ROOT . '/' . variable_get('path_inc', 'includes/path.inc');
  require_once DRUPAL_ROOT . '/includes/theme.inc';
  require_once DRUPAL_ROOT . '/includes/pager.inc';
  require_once DRUPAL_ROOT . '/' . variable_get('menu_inc', 'includes/menu.inc');
  require_once DRUPAL_ROOT . '/includes/tablesort.inc';
  require_once DRUPAL_ROOT . '/includes/file.inc';
  require_once DRUPAL_ROOT . '/includes/unicode.inc';
  require_once DRUPAL_ROOT . '/includes/image.inc';
  require_once DRUPAL_ROOT . '/includes/form.inc';
  require_once DRUPAL_ROOT . '/includes/mail.inc';
  require_once DRUPAL_ROOT . '/includes/actions.inc';
  require_once DRUPAL_ROOT . '/includes/ajax.inc';
  require_once DRUPAL_ROOT . '/includes/token.inc';
  require_once DRUPAL_ROOT . '/includes/errors.inc';

  // Detect string handling method
  // Undo magic quotes
  // Load all enabled modules
  // Make sure all stream wrappers are registered.

As for hook_boot() and hook_exit() being invoked, that happens depending on the value of a Drupal variable, since the code being used in _drupal_bootstrap_page_cache() is the following.

  // If the skipping of the bootstrap hooks is not enforced, call
  // hook_boot.
  if (variable_get('page_cache_invoke_hooks', TRUE)) {
  // If the skipping of the bootstrap hooks is not enforced, call
  // hook_exit.
  if (variable_get('page_cache_invoke_hooks', TRUE)) {

A hook that is always called when Drupal completes its bootstrap is, for example, hook_page_alter(). It is invoked when Drupal is rendering a page with drupal_render_page(); if you are checking when a user visits a page, that could be hook you could use.

  • Hi, I have already finished my simple module but was puzzled with your code. Please see my code in this link. Given my code on the link, should I use your code instead of mine? What benefits should I gain with your code? It seems that you have lots of required files included in the module. Is this not a speed issues compare to my code? BTW, I am using memcached and enabled Cache pages for anonymous users and Cache blocks. I'm willing to change my code if you can differentiate my code with yours. Thank you
    – jaypabs
    Aug 5, 2013 at 23:48

Your Answer

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

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