Skip to content

Commit

Permalink
Add support for Google Tag Manager
Browse files Browse the repository at this point in the history
  • Loading branch information
jelicanin committed Feb 1, 2019
1 parent 11dfc42 commit f483584
Show file tree
Hide file tree
Showing 7 changed files with 236 additions and 18 deletions.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

## Overview

Fast, configurable & simple Google Analytics module with support for multiple GA ID's
Fast, configurable, simple Google Analytics and Google Tag Manager module with support for multiple GA ID's

## Requirements

Expand All @@ -21,7 +21,7 @@ The master branch of this module is currently aiming for SilverStripe 4.x compat
- Install via Composer

```
composer require "fractas/googleanalytics" "^2.0"
composer require "fractas/googleanalytics" "^3.0"
```

- Add to your **mysite.yml** configuration file your Google Analytics ID, and enable extra features (if needed):
Expand All @@ -30,13 +30,14 @@ The master branch of this module is currently aiming for SilverStripe 4.x compat
Fractas\GoogleAnalytics\GoogleAnalyticsController:
enable_display_features: true # https://developers.google.com/analytics/devguides/collection/analyticsjs/display-features
enable_in_dev: false
ga_id: UA-xxxxxxxx-x0 #main GA ID property
ga_id: UA-xxxxxxxx-x0 #main Google Analytics ID property
gtm_id: GTM-xxxxxxxx #Google Tag Manager ID
ga_extra_ids:
newTracker1: UA-xxxxxxxx-x1 #multiple GA properties
newTracker1: UA-xxxxxxxx-x1 #you can add multiple Google Analytics ID properties
newTracker2: UA-xxxxxxxx-x2
newTracker3: UA-xxxxxxxx-x3
newTrackerX: UA-xxxxxxxx-xX
```
- Run flush=all in your browser
## Bugtracker
Expand Down
10 changes: 10 additions & 0 deletions _config/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,13 @@ name: googleanalyticsconfig
SilverStripe\CMS\Controllers\ContentController:
extensions:
- Fractas\GoogleAnalytics\GoogleAnalyticsController

---
After:
- requestprocessors
---
SilverStripe\Core\Injector\Injector:
SilverStripe\Control\Director:
properties:
Middlewares:
CustomTagMiddleware: '%$Fractas\GoogleAnalytics\GoogleTagManagerMiddleware'
11 changes: 6 additions & 5 deletions _config/mygaconfig.yml.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ name: mygaconfig
After: googleanalyticsconfig
---
Fractas\GoogleAnalytics\GoogleAnalyticsController:
enable_display_features: true
enable_in_dev: true
ga_id: UA-xxxxxxxx-x0
enable_display_features: true # https://developers.google.com/analytics/devguides/collection/analyticsjs/display-features
enable_in_dev: false
ga_id: UA-xxxxxxxx-x0 #main Google Analytics ID property
gtm_id: GTM-xxxxxxxx #Google Tag Manager ID
ga_extra_ids:
newTracker1: UA-xxxxxxxx-x1
newTracker1: UA-xxxxxxxx-x1 #you can add multiple Google Analytics ID properties
newTracker2: UA-xxxxxxxx-x2
newTracker3: UA-xxxxxxxx-x3
newTrackerX: UA-xxxxxxxx-xX
39 changes: 32 additions & 7 deletions src/GoogleAnalyticsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

namespace Fractas\GoogleAnalytics;

use SilverStripe\Core\Config\Config;
use SilverStripe\Control\Director;
use SilverStripe\View\ArrayData;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Extension;
use SilverStripe\ORM\ArrayList;
use SilverStripe\View\ArrayData;
use SilverStripe\View\Requirements;
use SilverStripe\Core\Extension;

class GoogleAnalyticsController extends Extension
{
Expand All @@ -21,6 +21,21 @@ class GoogleAnalyticsController extends Extension
*/
private static $ga_extra_ids;

/**
* @var string Google Tag Manager tracking code
*/
private static $gtm_id;

/**
* @var string Google Analytics domain, used for prefetch
*/
private static $ga_domain = 'https://www.google-analytics.com';

/**
* @var string Google Tag Manager domain, used for prefetch
*/
private static $gtm_domain = 'https://www.googletagmanager.com';

/**
* @var bool For details see https://support.google.com/analytics/answer/2444872?hl=en#trackingcode
*/
Expand All @@ -41,6 +56,16 @@ public function GAID()
}
}

/**
* @return string Returns Google Tag Manager ID if module is enabled
*/
public function GTMID()
{
if ($this->IsEnabled()) {
return Config::inst()->get(self::class, 'gtm_id');
}
}

/**
* @return bool Google Analytics Display Features is enabled?
*/
Expand Down Expand Up @@ -78,16 +103,16 @@ public function MultiTrackersList()
{
$list = Config::inst()->get(self::class, 'ga_extra_ids');

if (!is_array($list)) {
if (!\is_array($list)) {
return false;
}

$extra = array();
$extra = [];
foreach ($list as $key => $value) {
$extra[] = new ArrayData(array(
$extra[] = new ArrayData([
'Title' => $key,
'ID' => $value,
));
]);
}

return new ArrayList($extra);
Expand Down
171 changes: 171 additions & 0 deletions src/GoogleTagManagerMiddleware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
<?php

namespace Fractas\GoogleAnalytics;

use SilverStripe\Admin\AdminRootController;
use SilverStripe\Control\Director;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\Middleware\HTTPMiddleware;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\View\ArrayData;
use SilverStripe\View\HTML;

class GoogleTagManagerMiddleware implements HTTPMiddleware
{
use Injectable;
use Configurable;

/**
* @var string Google Tag Manager ID
*/
private $gtm_id = null;

/**
* @var string Google Tag Manager domain
*/
private $gtm_domain = null;

/**
* @var string Google Analytics domain
*/
private $ga_domain = null;

/**
* Process request.
*
* @param HTTPRequest $request
* @param callable $delegate
*
* @return $response
*/
public function process(HTTPRequest $request, callable $delegate)
{
$response = $delegate($request);

if (true === $this->getIsAdmin($request)) {
return $response;
}

if ($this->getIsEnabled()) {
$this->gtm_id = Config::inst()->get(GoogleAnalyticsController::class, 'gtm_id');
$this->gtm_domain = Config::inst()->get(GoogleAnalyticsController::class, 'gtm_domain');
$this->ga_domain = Config::inst()->get(GoogleAnalyticsController::class, 'ga_domain');

$this->addBodyTag($response);
$this->addHeadTag($response);
$this->addPrefetchGA($response);
$this->addPrefetchGTM($response);
$this->addPreconnectGA($response);
$this->addPreconnectGTM($response);
}

return $response;
}

private function addBodyTag(&$response)
{
$data = ArrayData::create(['GTMID' => $this->gtm_id]);
$tag = $data->renderWith('GoogleTagManagerNoscriptCode');
$body = $response->getBody();
$pattern = '/\<body.*\>/';
$replace = '${0}'."\n".$tag;
$newBody = preg_replace($pattern, $replace, $body);
$response->setBody($newBody);
}

private function addHeadTag(&$response)
{
$data = ArrayData::create(['GTMID' => $this->gtm_id]);
$tag = $data->renderWith('GoogleTagManagerCode');
$body = $response->getBody();
$body = str_replace('<head>', '<head>'.$tag, $body);
$response->setBody($body);
}

private function addPreconnectGA(&$response)
{
$atts = [
'rel' => 'preconnect',
'href' => $this->ga_domain,
];
$pfTag = "\n".HTML::createTag('link', $atts)."\n";
$body = $response->getBody();
$body = str_replace('<head>', '<head>'.$pfTag, $body);
$response->setBody($body);
}

private function addPreconnectGTM(&$response)
{
$atts = [
'rel' => 'preconnect',
'href' => $this->gtm_domain,
];
$pfTag = "\n".HTML::createTag('link', $atts)."\n";
$body = $response->getBody();
$body = str_replace('<head>', '<head>'.$pfTag, $body);
$response->setBody($body);
}

private function addPrefetchGA(&$response)
{
$atts = [
'rel' => 'dns-prefetch',
'href' => $this->ga_domain,
];
$pfTag = "\n".HTML::createTag('link', $atts)."\n";
$body = $response->getBody();
$body = str_replace('<head>', '<head>'.$pfTag, $body);
$response->setBody($body);
}

private function addPrefetchGTM(&$response)
{
$atts = [
'rel' => 'dns-prefetch',
'href' => $this->gtm_domain,
];
$pfTag = "\n".HTML::createTag('link', $atts)."\n";
$body = $response->getBody();
$body = str_replace('<head>', '<head>'.$pfTag, $body);
$response->setBody($body);
}

/**
* Determine whether the website is being viewed from an admin protected area or not
* (shamelessly stolen from https://github.com/silverstripe/silverstripe-subsites).
*
* @param HTTPRequest $request
*
* @return bool
*/
private function getIsAdmin(HTTPRequest $request)
{
$adminPaths = static::config()->get('admin_url_paths');
$adminPaths[] = AdminRootController::config()->get('url_base').'/';
$adminPaths[] = 'dev/';
$currentPath = rtrim($request->getURL(), '/').'/';
foreach ($adminPaths as $adminPath) {
if (substr($currentPath, 0, \strlen($adminPath)) === $adminPath) {
return true;
}
}

return false;
}

/**
* @return bool Google Analytics is enabled by default if is in "live" mode
*/
private function getIsEnabled()
{
if (Director::isLive()) {
return true;
} elseif (Director::isDev() && Config::inst()->get(GoogleAnalyticsController::class, 'enable_in_dev')) {
return true;
}

return false;
}
}
7 changes: 7 additions & 0 deletions templates/GoogleTagManagerCode.ss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','$GTMID');</script>
<!-- End Google Tag Manager -->
3 changes: 3 additions & 0 deletions templates/GoogleTagManagerNoscriptCode.ss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id={$GTMID}" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->

0 comments on commit f483584

Please sign in to comment.