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)