Display your traffic with the visitors module

The visitors module is a new Fork module created at Wijs to show recent visitors on a map. It uses Google Analytics integration and Google maps to fetch data and nicely display it. Next to these visitors, items from other modules can be shown on this map. The code is crafted for easy integration with other modules. You can add a location to these linked items and show them on the map with a link to their detail page.

A preview of the module can be seen at http://wijs.be/nl/bezoekers.

Google Analytics integration

The integration with Google Analytics is done with the official Google APIs Client Library for PHP. This makes sure all features of Analytics API v3 can be fully used. In the backend, the analytics account can be coupled on the settings page of this module. To obtain the needed Client Id and Client Secret, you can follow these steps:

  1. Visit googles api console
  2. Log in with the google account coupled to the wanted analytics profile
  3. Go to 'Services' and make sure the Analytics API is enabled
  4. Go to API access. Create a new client ID
  5. For redirect URI, choose your SITE_URL follewed by '/private/nl/visitors/settings'

Sadly, the API doesn't allow offline access so coupling the analytics account on your local machine will not work out of the box. You can bypass this by using a service like xip.io.

In the frontend, this API is used to fetch all visitors for your site in the last fully completed hour that have geographic coördinates. This is done with this code:

// create filters to make sure only items from the last hour containing geographic coördinates are fetched
$optParams = array(
	'filters' => 'ga:hour==' . $hour . ';ga:latitude!=0.0000',
	'dimensions' => 'ga:latitude,ga:longitude,ga:visitLength'
);

// fetch the items from google analytics
$data = $analytics->data_ga->get(urldecode('ga:' . $settings['profile']), $dateBegin, $dateEnd, 'ga:visitors', $optParams);

Integration with other modules

You can easily add a link between your own modules and the visitors to be able to show objects like portfolio items, events, testimonials or others on the visitors map. The visitors module contains two interface classes that should be implemented to make the integration work. The BackendVisitorsInterface is used to couple the objects to the map and the FrontendVisitorsInterface is used to link the items on the map to the correct url.

To create the coupling in the backend, you can create a file 'visitors.php' in the engine folder of the wanted module. This could look something like this: 

/**
 * Helper class to send portfolio items to the visitors module
 *
 * @author Wouter Sioen <wouter.sioen@wijs.be>
 */
class BackendPortfolioVisitors implements BackendVisitorsInterface
{
	/**
	 * This function is used to interact with the visitors module
	 * It returns an array in this format
	 * 	array(
	 * 		module::id => title
	 * 	)
	 * 
	 * @return array
	 */
	public static function getForVisitors()
	{
		return BackendModel::getDB()->getPairs(
			'SELECT CONCAT(?, ":::", i.id), i.title
			 FROM portfolio AS i
			 WHERE i.language = ?
			 ORDER BY i.title ASC',
			array('portfolio', BL::getWorkingLanguage())
		);
	}
}

In the frontend, the same file should be made and should return a url based on the id of the given item. It could look like this:

/**
 * Helper class to integrate the portfolio module with the visitors module
 *
 * @author Wouter Sioen <wouter.sioen@wijs.be>
 */
class FrontendPortfolioVisitors implements FrontendVisitorsInterface
{
	/**
	 * Gets the url for an item with a certain id
	 * 
	 * @param int $id
	 * @return string
	 */
	public static function getUrlForVisitors($id)
	{
		$url = FrontendNavigation::getUrlForBlock('portfolio', 'detail');

		return $url . '/' . FrontendModel::getDB()->getVar(
			'SELECT m.url
			 FROM portfolio AS p
			 INNER JOIN meta AS m ON m.id = p.meta_id
			 WHERE p.id = ? AND p.language = ?
			 LIMIT 1',
			array((int) $id, FRONTEND_LANGUAGE)
		);
	}
}

When the module is coupled, it will appear in the backend index action and in the settings action. You'll be able to add new items from that type and you can determine a marker color on the settings page.

Caching

To get a good performance and make sure no rate limits are reached, the results from Google Analytics aren't real time. Google Analytics only saves results with a maximum precision of one hour, so we decided to show the results from the last fully completed hour. When a new hour starts, the first visitor initiates a call to the Google Analytics API. The results are parsed in a script tag in the template and are cached using the Spoon Template caching system. This will make sure the least visitors possible have a delay when fetching a page.

// calculate the amount of seconds until the next hour starts
$cachedTime = - (time() % 3600) + 3600;

// cache the template for this amount of seconds
$this->tpl->cache(FRONTEND_LANGUAGE . '_visitorsWidget', $cachedTime);

Development

The visitors module is open sourced by Wijs and is free to use for everyone. If you find issues or want to improve the functionality of this module, you're welcome to add issues or fork the project on Github.