ga('create', 'UA-12345678-1');
ga('set', 'dimension1', 'value');
ga('send', 'pageview');
ga.apply(null, ['create', 'UA-12345678-1']);
ga.apply(null, ['set', 'dimension1', 'value']);
ga.apply(null, ['send', 'pageview']);
var commands = [
['create', 'UA-12345678-1'],
['set', 'dimension1', 'value'],
['send', 'pageview'],
];
for (var i = 0; i < commands.length; i++) {
ga.apply(null, commands[i]);
}
(function (drupalSettings) {
'use strict';
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
for (var i = 0; i < drupalSettings.ga.commands.length; i++) {
ga.apply(null, drupalSettings.ga.commands[i]);
}
})(drupalSettings);
analytics:
version: 8001
js:
js/analytics.js: {}
https://www.google-analytics.com/analytics.js: {type: external, attributes: { async: true } }
dependencies:
- core/drupalSettings
namespace Drupal\ga\AnalyticsCommand;
class Create {
}
Drupal\ga\AnalyticsCommand\Create
/src/AnalyticsCommand/Create.php
namespace Drupal\ga\AnalyticsCommand;
class Create {
protected $trackingId;
}
namespace Drupal\ga\AnalyticsCommand;
class Create {
protected $trackingId;
public function __construct($trackingId) {
$this->trackingId = $trackingId;
}
}
namespace Drupal\ga\AnalyticsCommand;
class Create {
protected $trackingId;
public function __construct($trackingId) {
$this->trackingId = $trackingId;
}
public function getSettingCommand() {
return ['create', $this->trackingId];
}
}
$createInstance = new \Drupal\ga\AnalyticsCommand\Create('UA-12345678-1');
print_r($createInstance->getSettingCommand());
//Array
//(
// [0] => create
// [1] => UA-12345678-1
//)
use \Drupal\ga\AnalyticsCommand\Create;
$createInstance = new Create('UA-12345678-1');
print_r($createInstance->getSettingCommand());
//Array
//(
// [0] => create
// [1] => UA-12345678-1
//)
namespace Drupal\ga\AnalyticsCommand;
class Send {
protected $hitType;
public function __construct($hitType) {
$this->hitType = $hitType;
}
public function getSettingCommand() {
return ['send', $this->hitType];
}
}
namespace Drupal\ga\AnalyticsCommand;
class Pageview extends Send {
}
namespace Drupal\ga\AnalyticsCommand;
class Pageview extends Send {
public function __construct() {
parent::__construct('pageview');
}
}
use Drupal\ga\AnalyticsCommand\Pageview;
$pageviewInstance = new Pageview();
print_r($pageviewInstance->getSettingCommand());
//Array
//(
// [0] => send
// [1] => pageview
//)
namespace Drupal\ga\AnalyticsCommand;
class Set {
protected $settingKey;
protected $settingValue;
public function __construct($settingKey, $settingValue) {
$this->settingKey = $settingKey;
$this->settingValue = $settingValue;
}
public function getSettingCommand() {
return ['set', $this->settingKey, $this->settingValue];
}
}
namespace Drupal\ga\AnalyticsCommand;
class SetDimension extends Set {
public function __construct($index, $value) {
parent::__construct('dimension' . $index, $value);
}
}
namespace Drupal\ga\AnalyticsCommand;
interface SettingItemInterface {
public function getSettingCommand();
}
namespace Drupal\ga\AnalyticsCommand;
class Send implements SettingItemInterface {
protected $hitType;
public function __construct($hitType) {
$this->hitType = $hitType;
}
public function getSettingCommand() {
return ['send', $this->hitType];
}
}
namespace Drupal\ga\AnalyticsCommand;
interface SettingItemInterface {
public function getSettingCommand();
public function getPriority();
}
namespace Drupal\ga\AnalyticsCommand;
class Create implements SettingItemInterface {
protected $trackingId;
protected $priority;
public function __construct($trackingId, $priority) {
$this->trackingId = $trackingId;
$this->priority = $priority;
}
public function getSettingCommand() {
return ['create', $this->trackingId];
}
public function getPriority() {
return $this->priority;
}
}
namespace Drupal\ga\AnalyticsCommand;
trait PrioritizedTrait {
protected $priority;
public function getPriority() {
return $this->priority;
}
}
namespace Drupal\gap\AnalyticsCommand;
class Create implements SettingItemInterface {
use PrioritizedTrait;
protected $trackingId;
public function __construct($trackingId, $priority) {
$this->trackingId = $trackingId;
$this->priority = $priority;
}
public function getSettingCommand() {
return ['create', $this->trackingId];
}
}
namespace Drupal\gap\AnalyticsCommand;
class Create implements SettingItemInterface {
use PrioritizedTrait;
const DEFAULT_PRIORITY = 300;
protected $trackingId;
public function __construct($trackingId, $priority = self::DEFAULT_PRIORITY) {
$this->trackingId = $trackingId;
$this->priority = $priority;
}
public function getSettingCommand() {
return ['create', $this->trackingId];
}
}
namespace Drupal\ga\Event;
use Drupal\ga\AnalyticsCommand\SettingItemInterface;
use Symfony\Component\EventDispatcher\Event;
class CollectEvent extends Event {
protected $commands;
public function __construct() {
$this->commands = [];
}
public function addCommand(SettingItemInterface $item) {
$this->commands[] = $item;
}
public function getDrupalSettingCommands() {
usort(
$this->commands,
function (SettingItemInterface $a, SettingItemInterface $b) {
return $b->getPriority() - $a->getPriority();
}
);
return array_map(
function (SettingItemInterface $item) {
return $item->getSettingCommand()
},
$this->commands
);
}
}
use Drupal\ga\Event\CollectEvent;
/**
* Implements hook_page_attachments().
*/
function ga_page_attachments(array &$attachments) {
$event = \Drupal::service('event_dispatcher')
->dispatch('ga.collect', new CollectEvent());
$attachments['#attached']['library'][] = 'ga/analytics';
$attachments['#attached']['drupalSettings']['ga']['commands'] =
$event->getDrupalSettingCommands();
}
namespace Drupal\ga\EventSubscriber;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\ga\AnalyticsCommand\Create;
use Drupal\ga\AnalyticsCommand\Pageview;
use Drupal\ga\Event\CollectEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class DefaultCommandSubscriber implements EventSubscriberInterface {
protected $configFactory;
public static function getSubscribedEvents() {
return [
'ga.collect' => [
['onCollectDefaultCommands'],
],
];
}
public function __construct(ConfigFactoryInterface $configFactory) {
$this->configFactory = $configFactory;
}
public function onCollectDefaultCommands(CollectEvent $event) {
$config = $this->configFactory->get('ga.settings');
$event->addCommand(new Create($config->get('tracking_id')));
$event->addCommand(new Pageview());
}
}
services:
ga.default_command_subscriber:
class: Drupal\ga\EventSubscriber\DefaultCommandSubscriber
arguments: ['@config.factory']
tags:
- { name: event_subscriber }
namespace Drupal\my_module\EventSubscriber;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\ga\AnalyticsCommand\SetDimension;
use Drupal\ga\Event\CollectEvent;
use Drupal\node\NodeInterface;
use Drupal\taxonomy\TermInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class EntityAnalyticsSubscriber implements EventSubscriberInterface {
protected $routeMatch;
public static function getSubscribedEvents() {
return [
'ga.collect' => [
['onCollect'],
],
];
}
public function __construct(RouteMatchInterface $routeMatch) {
$this->routeMatch = $routeMatch;
}
public function onCollect(CollectEvent $event) {
if (($node = $this->routeMatch->getParameter('node'))) {
$this->applyAttributesFromNode($event, $node);
}
elseif (($term = $this->routeMatch->getParameter('taxonomy_term'))) {
$this->applyAttributesFromTaxonomyTerm($event, $term);
}
}
protected function applyAttributesFromNode(CollectEvent $event, NodeInterface $node) {
if (!empty($node->field_category[0]->entity)) {
$category = $node->field_category[0]->entity->name->value;
$event->addCommand(new SetDimension(1, $category));
}
}
protected function applyAttributesFromTaxonomyTerm(CollectEvent $event, TermInterface $term) {
$event->addCommand(new SetDimension(1, $term->name->value));
}
}
namespace Drupal\ga\AnalyticsCommand;
class SetMetric extends Set {
public function __construct($index, $value, $priority = self::DEFAULT_PRIORITY) {
if (!is_int($index)) {
throw new \InvalidArgumentException("Metric index must be a positive integer.");
}
if (!is_numeric($value)) {
throw new \InvalidArgumentException("Metric value must be a number.");
}
parent::__construct('dimension' . $index, $value, $priority);
}
}
class EntityAnalyticsSubscriber implements EventSubscriberInterface {
public function onCollect(CollectEvent $event) {
try {
$event->addCommand(new SetMetric(1, 'string'));
}
catch (\InvalidArgumentException $exception) {
$this->logger->error($exception->getMessage());
}
}
}
namespace Drupal\ga\Form;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
class AdminSettingsForm extends ConfigFormBase {
public function getFormId() {
return 'ga_admin_settings';
}
protected function getEditableConfigNames() {
return ['ga.settings'];
}
public function buildForm(array $form, FormStateInterface $form_state) {
$config = $this->config('ga.settings');
$form['tracking_id'] = [
'#type' => 'textfield',
'#title' => $this->t('Web Property Tracking ID'),
'#default_value' => $config->get('tracking_id'),
];
return parent::buildForm($form, $form_state);
}
public function validateForm(array &$form, FormStateInterface $form_state) {
parent::validateForm($form, $form_state);
$property = $form_state->getValue('tracking_id');
if (!empty($property) && !preg_match('/^UA-\d+-\d+$/', $property)) {
$form_state->setErrorByName(
'tracking_id',
$this->t('The provided Tracking ID is not valid.')
);
}
}
public function submitForm(array &$form, FormStateInterface $form_state) {
$this->config('ga.settings')
->set('tracking_id', $form_state->getValue('tracking_id'))
->save();
parent::submitForm($form, $form_state);
}
}
namespace Drupal\Tests\ga\Unit\AnalyticsCommand;
use Drupal\ga\AnalyticsCommand\Create;
use Drupal\Tests\UnitTestCase;
class CreateTest extends UnitTestCase {
public function testDefaultPriority() {
$command = new Create('UA-12345678-1');
$this->assertEquals(300, $command->getPriority());
}
public function testBasicSettingCommands() {
$command = new Create('UA-12345678-1');
$this->assertEquals(['create', 'UA-12345678-1'], $command->getSettingCommand());
}
}
namespace Drupal\Tests\ga\Unit\Event;
use Drupal\ga\Event\CollectEvent;
use Drupal\Tests\UnitTestCase;
class CollectEventTest extends UnitTestCase {
private $event;
public function setUp() {
parent::setUp();
$this->event = new CollectEvent();
}
public function testEmptyCollection() {
$result = $this->event->getDrupalSettingCommands();
$this->assertEquals([], $result);
}
public function testCreateSend() {
$this->event->addCommand(new Create('UA-12345678-1'));
$this->event->addCommand(new Pageview());
$result = $this->event->getDrupalSettingCommands();
$this->assertEquals(
[['create', 'UA-12345678-1'], ['send', 'pageview']],
$result
);
}
public function testSendCreate() {
$this->event->addCommand(new Pageview());
$this->event->addCommand(new Create('UA-12345678-1'));
$result = $this->event->getDrupalSettingCommands();
$this->assertEquals(
[['create', 'UA-12345678-1'], ['send', 'pageview']],
$result
);
}
}
$ vendor/bin/phpunit --configuration core/phpunit.xml modules/ga
Testing started at 11:33 PM ...
PHPUnit 4.8.26 by Sebastian Bergmann and contributors.
Time: 11.66 seconds, Memory: 6.00MB
OK (71 tests, 117 assertions)