diff --git a/README.md b/README.md index 4c909d7..edeceb1 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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): @@ -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 diff --git a/_config/config.yml b/_config/config.yml index 10449bd..8a1fa1a 100755 --- a/_config/config.yml +++ b/_config/config.yml @@ -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' diff --git a/_config/mygaconfig.yml.example b/_config/mygaconfig.yml.example index d79f265..cb6ef90 100755 --- a/_config/mygaconfig.yml.example +++ b/_config/mygaconfig.yml.example @@ -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 diff --git a/src/GoogleAnalyticsController.php b/src/GoogleAnalyticsController.php index 8c0106d..7d5ec16 100755 --- a/src/GoogleAnalyticsController.php +++ b/src/GoogleAnalyticsController.php @@ -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 { @@ -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 */ @@ -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? */ @@ -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); diff --git a/src/GoogleTagManagerMiddleware.php b/src/GoogleTagManagerMiddleware.php new file mode 100644 index 0000000..c3bd700 --- /dev/null +++ b/src/GoogleTagManagerMiddleware.php @@ -0,0 +1,171 @@ +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 = '/\/'; + $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('', ''.$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('', ''.$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('', ''.$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('', ''.$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('', ''.$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; + } +} diff --git a/templates/GoogleTagManagerCode.ss b/templates/GoogleTagManagerCode.ss new file mode 100644 index 0000000..3de9eef --- /dev/null +++ b/templates/GoogleTagManagerCode.ss @@ -0,0 +1,7 @@ + + + diff --git a/templates/GoogleTagManagerNoscriptCode.ss b/templates/GoogleTagManagerNoscriptCode.ss new file mode 100644 index 0000000..3f71661 --- /dev/null +++ b/templates/GoogleTagManagerNoscriptCode.ss @@ -0,0 +1,3 @@ + + +