Drupal + BBClone
I like BBCLONE's visitor statistics package. It has served us well for more than a few years. Our customers like it too. There is a problem though. Drupal and BBClone do not get along very well. Here are a couple of tips to get BBClone working with virtual hosts (multiple sites hosted via one single drupal installation), and with caching enabled.
Most of the helpful hints proposed on http://drupal.org/ suggest installing the relevant BBClone code in the ~drupal/index.php file, like so:
$bbrequest = strtolower($_SERVER["REQUEST_URI"]);
define("_BBC_PAGE_NAME", $bbrequest);
define("_BBCLONE_DIR", "bbclone/");
define("COUNTER", _BBCLONE_DIR."mark_page.php");
if (is_readable(COUNTER)) include_once(COUNTER);
This is all fine and good, but if you are hosting multiple sites under ~drupal/sites/ then you are going to have a problem. Each virtual site has its own statistics counter and bbclone directory. We want each site to count only its own vistors.
First, we must add some sort of drupal path function to indicate where each particular bbclone directory would be for that particular host. This would be part of Drupal's internal set of variables to indicate which directory hold which site. conf_path(), looks to be the correct choice. conf_path() returns the file system directory starting from the drupal base. I assigned it to a variable I called $bbclone_dir. I added the following the Drupal bootstrap function, drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL) like so:
$bbrequest = strtolower($_SERVER["REQUEST_URI"]);
define("_BBC_PAGE_NAME", $bbrequest);
$bbclone_dir=conf_path();
define("_BBCLONE_DIR", "$bbclone_dir/bbclone/");
define("COUNTER", _BBCLONE_DIR."mark_page.php");
if (is_readable(COUNTER)) include_once(COUNTER);
This particular solution worked, but yielded another set of problems. With caching turned on, BBClone ceased to register new visits except to uncached pages. If you were logged in, you registered fine. If you hit a page that was not already cached, you registered fine. But if you were an anonymous user and you hit a cached page, you would never show up. We can't have that.
My tentative solution was to figure out where ~drupal/index.php decided if a page was cached or not. My thinking was this: ~drupal/index.php must be hit each and every single time a visitor requests a page. It must determine whether a page is cached or not, deliver it, or generate a new one. What I need from this page is for BBClone to register a hit regardless of whether a page is cached or not. If I reference BBClone at the top of the page, my reference to the function conf_path() will throw an error because it doesn't exist. If I include it too late, the page is already determined to be cached and I get no record of the visit.
Anyway, the problem seems to be solved by inserting the above BBClone code between the Drupal bootstrap process like so:
require_once './includes/bootstrap.inc';
$bbrequest = strtolower($_SERVER["REQUEST_URI"]);
define("_BBC_PAGE_NAME", $bbrequest);
$bbclone_dir=conf_path();
define("_BBCLONE_DIR", "$bbclone_dir/bbclone/");
define("COUNTER", _BBCLONE_DIR."mark_page.php");
if (is_readable(COUNTER)) include_once(COUNTER);
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
It is in the drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); where I believe Drupal determines a page's state (cached or not) and reacts accordingly. I checked http://api.drupal.org/api/function/drupal_bootstrap/6 and find that there are several possible phases of which DRUPAL_BOOTSTRAP_FULL is the full stack. DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE is the second phase and seems to be what I was looking for. By calling the bootstrap after BBClone, hits are registered as expected. Time will tell if not calling DRUPAL_BOOTSTRAP_CONFIGURATION first screws things up in some way.
For now, though, it does work. All hits get registered on cached and uncached pages or anonymous and authenticated users and independently on all virtual hosts where BBClone is installed..

