Skip to content

Commit

Permalink
Add Google Tag Manager support (vufind-org#2637)
Browse files Browse the repository at this point in the history
  • Loading branch information
maccabeelevine authored and doug-hahn committed Jul 21, 2023
1 parent ef166c0 commit 8863651
Show file tree
Hide file tree
Showing 6 changed files with 296 additions and 0 deletions.
6 changes: 6 additions & 0 deletions config/vufind/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2006,6 +2006,12 @@ treeSearchLimit = 100
; Analytics and Matomo/Piwik), look at the wiki page:
; https://vufind.org/wiki/configuration:usage_stats

; Uncomment this section and provide your Container ID key to enable Google Tag Manager.
; For information on installing GTM and identifying your GTM Container ID, see:
; https://support.google.com/tagmanager/answer/6103696
;[GoogleTagManager]
;gtmContainerId = "GTM-1234567"

; Uncomment this section and provide your API key to enable Google Analytics. Be
; sure to set the "universal" setting to true once your account is upgraded to
; Universal Analytics; see:
Expand Down
105 changes: 105 additions & 0 deletions module/VuFind/src/VuFind/View/Helper/Root/GoogleTagManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php
/**
* GoogleTagManager view helper
*
* PHP version 7
*
* Copyright (C) Villanova University 2022.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* @category VuFind
* @package View_Helpers
* @author Maccabee Levine <[email protected]>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org Main Site
*/
namespace VuFind\View\Helper\Root;

/**
* GoogleTagManager view helper
*
* @category VuFind
* @package View_Helpers
* @author Maccabee Levine <[email protected]>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org Main Site
*/
class GoogleTagManager extends \Laminas\View\Helper\AbstractHelper
{
/**
* GTM Container ID (false if disabled)
*
* @var string|bool
*/
protected $gtmContainerId;

/**
* Constructor
*
* @param string|bool $gtmContainerId Container ID (false if disabled)
*/
public function __construct($gtmContainerId)
{
$this->gtmContainerId = $gtmContainerId;
}

/**
* Returns GTM code block meant for the <head> element.
*
* @return string
*/
public function getHeadCode()
{
if (!$this->gtmContainerId) {
return '';
}

// phpcs:disable -- line length should be kept for this vendor snippet
$js = <<<END
(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;var n=d.querySelector('[nonce]');
n&&j.setAttribute('nonce',n.nonce||n.getAttribute('nonce'));f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','{$this->gtmContainerId}');
END;
// phpcs:enable
$inlineScript = $this->getView()->plugin('inlinescript');
$js = $inlineScript(\Laminas\View\Helper\HeadScript::SCRIPT, $js, 'SET');
return $js;
}

/**
* Returns GTM code block meant for the <body> element.
*
* @return string
*/
public function getBodyCode()
{
if (!$this->gtmContainerId) {
return '';
}

// phpcs:disable -- line length should be kept for this vendor snippet
$js = <<<END
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id={$this->gtmContainerId}"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
END;
// phpcs:enable
return $js;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php
/**
* GoogleTagManager helper factory.
*
* PHP version 7
*
* Copyright (C) Villanova University 2022.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* @category VuFind
* @package View_Helpers
* @author Maccabee Levine <[email protected]>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development Wiki
*/
namespace VuFind\View\Helper\Root;

use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
use Laminas\ServiceManager\Factory\FactoryInterface;
use Psr\Container\ContainerExceptionInterface as ContainerException;
use Psr\Container\ContainerInterface;

/**
* GoogleTagManager helper factory.
*
* @category VuFind
* @package View_Helpers
* @author Maccabee Levine <[email protected]>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development Wiki
*/
class GoogleTagManagerFactory implements FactoryInterface
{
/**
* Create an object
*
* @param ContainerInterface $container Service manager
* @param string $requestedName Service being created
* @param null|array $options Extra options (optional)
*
* @return object
*
* @throws ServiceNotFoundException if unable to resolve the service.
* @throws ServiceNotCreatedException if an exception is raised when
* creating a service.
* @throws ContainerException&\Throwable if any other error occurs
*/
public function __invoke(
ContainerInterface $container,
$requestedName,
array $options = null
) {
if (!empty($options)) {
throw new \Exception('Unexpected options sent to factory.');
}
$config = $container->get(\VuFind\Config\PluginManager::class)
->get('config');
$gtmContainerId = $config->GoogleTagManager->gtmContainerId ?? false;
return new $requestedName($gtmContainerId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php
/**
* GoogleTagManager view helper Test Class
*
* PHP version 7
*
* Copyright (C) Villanova University 2022.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* @category VuFind
* @package Tests
* @author Maccabee Levine <[email protected]>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development:testing:unit_tests Wiki
*/
namespace VuFindTest\View\Helper\Root;

use VuFind\View\Helper\Root\GoogleTagManager;

/**
* GoogleTagManager view helper Test Class
*
* @category VuFind
* @package Tests
* @author Maccabee Levine <[email protected]>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development:testing:unit_tests Wiki
*/
class GoogleTagManagerTest extends \PHPUnit\Framework\TestCase
{
use \VuFindTest\Feature\ViewTrait;

/**
* Test getHeadCode()
*
* @return void
*/
public function testHeadCode(): void
{
$output = $this->renderGTMHeadCode('fakeContainerId');
$this->assertTrue(false !== strstr($output, 'gtm.js'));
$this->assertTrue(false !== strstr($output, 'fakeContainerId'));
}

/**
* Test getBodyCode()
*
* @return void
*/
public function testBodyCode(): void
{
$output = $this->renderGTMBodyCode('fakeContainerId');
$this->assertTrue(false !== strstr($output, 'ns.html'));
$this->assertTrue(false !== strstr($output, 'fakeContainerId'));
}

/**
* Test the helper (disabled mode)
*
* @return void
*/
public function testDisabled(): void
{
$this->assertEquals('', $this->renderGTMHeadCode(false));
$this->assertEquals('', $this->renderGTMBodyCode(false));
}

/**
* Render the GTM Head element code
*
* @param string $gtmContainerId GTM Container ID (false for disabled)
*
* @return string
*/
protected function renderGTMHeadCode(string $gtmContainerId): string
{
$helper = new GoogleTagManager($gtmContainerId);
$helper->setView($this->getPhpRenderer());
return (string)$helper->getHeadCode();
}

/**
* Render the GTM Body element code
*
* @param string $gtmContainerId GTM Container ID (false for disabled)
*
* @return string
*/
protected function renderGTMBodyCode(string $gtmContainerId): string
{
$helper = new GoogleTagManager($gtmContainerId);
$helper->setView($this->getPhpRenderer());
return (string)$helper->getBodyCode();
}
}
2 changes: 2 additions & 0 deletions themes/bootstrap3/templates/layout/layout.phtml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<?=$this->headMeta()?>
<?=$this->googleTagManager()->getHeadCode()?>

<?php
// Format the page title using the translation system:
Expand Down Expand Up @@ -145,6 +146,7 @@ JS;
</div>
</div>
<div class="offcanvas-overlay" data-toggle="offcanvas"></div>
<?=$this->googleTagManager()->getBodyCode()?>
<?=$this->googleanalytics()?>
<?=$this->piwik()?>
<?=$this->matomo()?>
Expand Down
2 changes: 2 additions & 0 deletions themes/root/theme.config.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
'VuFind\View\Helper\Root\Flashmessages' => 'VuFind\View\Helper\Root\FlashmessagesFactory',
'VuFind\View\Helper\Root\GeoCoords' => 'VuFind\View\Helper\Root\GeoCoordsFactory',
'VuFind\View\Helper\Root\GoogleAnalytics' => 'VuFind\View\Helper\Root\GoogleAnalyticsFactory',
'VuFind\View\Helper\Root\GoogleTagManager' => 'VuFind\View\Helper\Root\GoogleTagManagerFactory',
'VuFind\View\Helper\Root\HelpText' => 'VuFind\View\Helper\Root\HelpTextFactory',
'VuFind\View\Helper\Root\Highlight' => 'Laminas\ServiceManager\Factory\InvokableFactory',
'VuFind\View\Helper\Root\HistoryLabel' => 'VuFind\View\Helper\Root\HistoryLabelFactory',
Expand Down Expand Up @@ -106,6 +107,7 @@
'flashmessages' => 'VuFind\View\Helper\Root\Flashmessages',
'geocoords' => 'VuFind\View\Helper\Root\GeoCoords',
'googleanalytics' => 'VuFind\View\Helper\Root\GoogleAnalytics',
'googleTagManager' => 'VuFind\View\Helper\Root\GoogleTagManager',
'helpText' => 'VuFind\View\Helper\Root\HelpText',
'highlight' => 'VuFind\View\Helper\Root\Highlight',
'historylabel' => 'VuFind\View\Helper\Root\HistoryLabel',
Expand Down

0 comments on commit 8863651

Please sign in to comment.