├── README.md
└── app
├── code
└── community
│ └── CVM
│ └── GoogleTagManager
│ ├── Block
│ └── Gtm.php
│ ├── Helper
│ └── Data.php
│ ├── Model
│ └── Observer.php
│ └── etc
│ ├── adminhtml.xml
│ ├── config.xml
│ └── system.xml
├── design
└── frontend
│ └── base
│ └── default
│ ├── layout
│ └── googletagmanager.xml
│ └── template
│ └── googletagmanager
│ └── gtm.phtml
└── etc
└── modules
└── CVM_GoogleTagManager.xml
/README.md:
--------------------------------------------------------------------------------
1 | # Google Tag Manager
2 |
3 | A standard implementation of [Google Tag Manager][1] for [Magento][2], with data layer support for transaction and visitor data.
4 |
5 | ## Features
6 |
7 | ### Built in data layer support
8 |
9 | Use the data layer to enable Google Analytics e-commerce tracking using Google Tag Manager's native tags. You can also build more flexible macros in GTM using visitor data.
10 |
11 | ### The future
12 |
13 | Additional data layer work is planned for future releases, starting with site search data.
14 |
15 | This extension is made available for free. Any donations toward maintaining it and adding new features as Google Tag Manager evolves are greatly appreciated.
16 |
17 | [][3]
18 |
19 | ## Installation
20 |
21 | The latest version of this extension can be downloaded via [Magento Connect][4] and installed via Magento Connect Manager.
22 |
23 | Alternatively, you can also clone or download this repository and copy the app directory into the root of your Magento installation (not recommended unless you're sure you know what you're doing).
24 |
25 | ## Usage
26 |
27 | Log in to your Magento installation's admin and navigate to `System > Configuration > Sales > Google API`. If installed correctly, you should see a new section below Google Analytics for Google Tag Manager.
28 |
29 | ### Deploying the tag container
30 |
31 | To deploy the tag container on all your pages, switch the `Enable` option to `Yes` and enter your `Container Public ID`. This can be found in the Google Tag Manager interface, and takes the form `GTM-XXXX`.
32 |
33 | ### Enabling the data layer
34 |
35 | The data layer provides Google Tag Manager with additional data that can be used to form macros which can in turn be used for creating rules that dictate when specific tags will fire. It is also populated with transaction data when orders are placed, facilitating Google Analytics e-commerce tracking when using the appropriate tag in Google Tag Manager.
36 |
37 | The data layer is disabled by default and can be enabled independently for both transaction and visitor data. To do this, change the `Data layer: Transactions` or `Data layer: Visitors` options to `Enable`.
38 |
39 | For transactions, there are additional fields for `transactionType` and `transactionAffiliation` that can take custom values, depending on the store view. These can be left blank if desired, or populated to allow Google Tag Manager to fire different tags for different stores.
40 |
41 | ## Support
42 |
43 | Please report bugs and feature requests using the [Github issue tracker][6].
44 |
45 | [1]:http://www.google.com/tagmanager
46 | [2]:http://www.magentocommerce.com/
47 | [3]:https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=XZMM6SFDTPCAA
48 | [4]:http://www.magentocommerce.com/magento-connect/
49 | [5]:https://support.google.com/tagmanager/
50 | [6]:https://github.com/CVM/Magento_GoogleTagManager/issues
--------------------------------------------------------------------------------
/app/code/community/CVM/GoogleTagManager/Block/Gtm.php:
--------------------------------------------------------------------------------
1 |
8 | * @copyright Copyright (c) 2013 Chris Martin
9 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License 3.0 (OSL-3.0)
10 | */
11 | class CVM_GoogleTagManager_Block_Gtm extends Mage_Core_Block_Template
12 | {
13 | /**
14 | * Generate JavaScript for the container snippet.
15 | *
16 | * @return string
17 | */
18 | protected function _getContainerSnippet()
19 | {
20 | // Get the container ID.
21 | $containerId = Mage::helper('googletagmanager')->getContainerId();
22 |
23 | // Render the container snippet JavaScript.
24 | return "
26 | \n";
31 | }
32 |
33 | /**
34 | * Generate JavaScript for the data layer.
35 | *
36 | * @return string|null
37 | */
38 | protected function _getDataLayer()
39 | {
40 | // Initialise our data source.
41 | $data = array();
42 |
43 | // Get transaction and visitor data, if desired.
44 | if (Mage::helper('googletagmanager')->isDataLayerTransactionsEnabled()) $data = $data + $this->_getTransactionData();
45 | if (Mage::helper('googletagmanager')->isDataLayerVisitorsEnabled()) $data = $data + $this->_getVisitorData();
46 |
47 | // Enable modules to add custom data to the data layer
48 | $data_layer = new Varien_Object();
49 | $data_layer->setData($data);
50 | Mage::dispatchEvent('cvm_googletagmanager_get_datalayer',
51 | array('data_layer' => $data_layer)
52 | );
53 | $data = $data_layer->getData();
54 |
55 | // Generate the data layer JavaScript.
56 | if (!empty($data)) return "\n\n";
57 | else return '';
58 | }
59 |
60 | /**
61 | * Get transaction data for use in the data layer.
62 | *
63 | * @link https://developers.google.com/tag-manager/reference
64 | * @return array
65 | */
66 | protected function _getTransactionData()
67 | {
68 | $data = array();
69 |
70 | $orderIds = $this->getOrderIds();
71 | if (empty($orderIds) || !is_array($orderIds)) return array();
72 |
73 | $collection = Mage::getResourceModel('sales/order_collection')->addFieldToFilter('entity_id', array('in' => $orderIds));
74 |
75 | $i = 0;
76 | $products = array();
77 |
78 | foreach ($collection as $order) {
79 | if ($i == 0) {
80 | // Build all fields for first order.
81 | $data = array(
82 | 'event' => 'transaction',
83 | 'transactionId' => $order->getIncrementId(),
84 | 'transactionDate' => date("Y-m-d"),
85 | 'transactionType' => Mage::helper('googletagmanager')->getTransactionType(),
86 | 'transactionAffiliation' => Mage::helper('googletagmanager')->getTransactionAffiliation(),
87 | 'transactionTotal' => round($order->getBaseGrandTotal(),2),
88 | 'transactionShipping' => round($order->getBaseShippingAmount(),2),
89 | 'transactionTax' => round($order->getBaseTaxAmount(),2),
90 | 'transactionPaymentType' => $order->getPayment()->getMethodInstance()->getTitle(),
91 | 'transactionCurrency' => $order->getOrderCurrencyCode(),
92 | 'transactionShippingMethod' => $order->getShippingCarrier()->getCarrierCode(),
93 | 'transactionPromoCode' => $order->getCouponCode(),
94 | 'transactionProducts' => array()
95 | );
96 | } else {
97 | // For subsequent orders, append to order ID, totals and shipping method.
98 | $data['transactionId'] .= '|'.$order->getIncrementId();
99 | $data['transactionTotal'] += $order->getBaseGrandTotal();
100 | $data['transactionShipping'] += $order->getBaseShippingAmount();
101 | $data['transactionTax'] += $order->getBaseTaxAmount();
102 | $data['transactionShippingMethod'] .= '|'.$order->getShippingCarrier()->getCarrierCode();
103 | }
104 |
105 | // Build products array.
106 | foreach ($order->getAllVisibleItems() as $item) {
107 | $product = Mage::getModel('catalog/product')->load($item->getProductId());
108 | $product_categories = $product->getCategoryIds();
109 | $categories = array();
110 | foreach ($product_categories as $category) {
111 | $categories[] = Mage::getModel('catalog/category')->load($category)->getName();
112 | }
113 | if (empty($products[$item->getSku()])) {
114 | // Build all fields the first time we encounter this item.
115 | $products[$item->getSku()] = array(
116 | 'name' => $this->jsQuoteEscape(Mage::helper('core')->escapeHtml($item->getName())),
117 | 'sku' => $this->jsQuoteEscape(Mage::helper('core')->escapeHtml($item->getSku())),
118 | 'category' => implode('|',$categories),
119 | 'price' => (double)number_format($item->getBasePrice(),2,'.',''),
120 | 'quantity' => (int)$item->getQtyOrdered()
121 | );
122 | } else {
123 | // If we already have the item, update quantity.
124 | $products[$item->getSku()]['quantity'] += (int)$item->getQtyOrdered();
125 | }
126 | }
127 |
128 | $i++;
129 | }
130 |
131 | // Push products into main data array.
132 | foreach ($products as $product) {
133 | $data['transactionProducts'][] = $product;
134 | }
135 |
136 | // Trim empty fields from the final output.
137 | foreach ($data as $key => $value) {
138 | if (!is_numeric($value) && empty($value)) unset($data[$key]);
139 | }
140 |
141 | return $data;
142 | }
143 |
144 | /**
145 | * Get visitor data for use in the data layer.
146 | *
147 | * @link https://developers.google.com/tag-manager/reference
148 | * @return array
149 | */
150 | protected function _getVisitorData()
151 | {
152 | $data = array();
153 | $customer = Mage::getSingleton('customer/session');
154 |
155 | // visitorId
156 | if ($customer->getCustomerId()) $data['visitorId'] = (string)$customer->getCustomerId();
157 |
158 | // visitorLoginState
159 | $data['visitorLoginState'] = ($customer->isLoggedIn()) ? 'Logged in' : 'Logged out';
160 |
161 | // visitorType
162 | $data['visitorType'] = (string)Mage::getModel('customer/group')->load($customer->getCustomerGroupId())->getCode();
163 |
164 | // visitorExistingCustomer / visitorLifetimeValue
165 | $orders = Mage::getResourceModel('sales/order_collection')->addFieldToSelect('*')->addFieldToFilter('customer_id',$customer->getId());
166 | $ordersTotal = 0;
167 | foreach ($orders as $order) {
168 | $ordersTotal += $order->getGrandTotal();
169 | }
170 | if ($customer->isLoggedIn()) {
171 | $data['visitorLifetimeValue'] = round($ordersTotal,2);
172 | } else {
173 | $orderData = $this->_getTransactionData();
174 | if (!empty($orderData)) {
175 | $data['visitorLifetimeValue'] = $orderData['transactionTotal'];
176 | } else {
177 | $data['visitorLifetimeValue'] = 0;
178 | }
179 | }
180 | $data['visitorExistingCustomer'] = ($ordersTotal > 0) ? 'Yes' : 'No';
181 |
182 | return $data;
183 | }
184 |
185 | /**
186 | * Render Google Tag Manager code
187 | *
188 | * @return string
189 | */
190 | protected function _toHtml()
191 | {
192 | if (!Mage::helper('googletagmanager')->isGoogleTagManagerAvailable()) return '';
193 | return parent::_toHtml();
194 | }
195 | }
196 |
--------------------------------------------------------------------------------
/app/code/community/CVM/GoogleTagManager/Helper/Data.php:
--------------------------------------------------------------------------------
1 |
8 | * @copyright Copyright (c) 2013 Chris Martin
9 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License 3.0 (OSL-3.0)
10 | */
11 | class CVM_GoogleTagManager_Helper_Data extends Mage_Core_Helper_Abstract
12 | {
13 | const XML_PATH_ACTIVE = 'google/googletagmanager/active';
14 | const XML_PATH_CONTAINER = 'google/googletagmanager/containerid';
15 |
16 | const XML_PATH_DATALAYER_TRANSACTIONS = 'google/googletagmanager/datalayertransactions';
17 | const XML_PATH_DATALAYER_TRANSACTIONTYPE = 'google/googletagmanager/datalayertransactiontype';
18 | const XML_PATH_DATALAYER_TRANSACTIONAFFILIATION = 'google/googletagmanager/datalayertransactionaffiliation';
19 |
20 | const XML_PATH_DATALAYER_VISITORS = 'google/googletagmanager/datalayervisitors';
21 |
22 | /**
23 | * Determine if GTM is ready to use.
24 | *
25 | * @return bool
26 | */
27 | public function isGoogleTagManagerAvailable()
28 | {
29 | return Mage::getStoreConfig(self::XML_PATH_CONTAINER) && Mage::getStoreConfigFlag(self::XML_PATH_ACTIVE);
30 | }
31 |
32 | /**
33 | * Get the GTM container ID.
34 | *
35 | * @return string
36 | */
37 | public function getContainerId() {
38 | return Mage::getStoreConfig(self::XML_PATH_CONTAINER);
39 | }
40 |
41 | /**
42 | * Add transaction data to the data layer?
43 | *
44 | * @return bool
45 | */
46 | public function isDataLayerTransactionsEnabled()
47 | {
48 | return Mage::getStoreConfig(self::XML_PATH_DATALAYER_TRANSACTIONS);
49 | }
50 |
51 | /**
52 | * Get the transaction type.
53 | *
54 | * @return string
55 | */
56 | public function getTransactionType() {
57 | if (!Mage::getStoreConfig(self::XML_PATH_DATALAYER_TRANSACTIONTYPE)) return '';
58 | return Mage::getStoreConfig(self::XML_PATH_DATALAYER_TRANSACTIONTYPE);
59 | }
60 |
61 | /**
62 | * Get the transaction affiliation.
63 | *
64 | * @return string
65 | */
66 | public function getTransactionAffiliation() {
67 | if (!Mage::getStoreConfig(self::XML_PATH_DATALAYER_TRANSACTIONAFFILIATION)) return '';
68 | return Mage::getStoreConfig(self::XML_PATH_DATALAYER_TRANSACTIONAFFILIATION);
69 | }
70 |
71 | /**
72 | * Add visitor data to the data layer?
73 | *
74 | * @return bool
75 | */
76 | public function isDataLayerVisitorsEnabled()
77 | {
78 | return Mage::getStoreConfig(self::XML_PATH_DATALAYER_VISITORS);
79 | }
80 | }
--------------------------------------------------------------------------------
/app/code/community/CVM/GoogleTagManager/Model/Observer.php:
--------------------------------------------------------------------------------
1 |
8 | * @copyright Copyright (c) 2013 Chris Martin
9 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License 3.0 (OSL-3.0)
10 | */
11 | class CVM_GoogleTagManager_Model_Observer
12 | {
13 | /**
14 | * Add order data to GTM block (for subsequent rendering in the data layer).
15 | *
16 | * @param Varien_Event_Observer $observer
17 | */
18 | public function setGoogleTagManagerTransactionData(Varien_Event_Observer $observer)
19 | {
20 | $orderIds = $observer->getEvent()->getOrderIds();
21 | if (empty($orderIds) || !is_array($orderIds)) return;
22 | $block = Mage::app()->getFrontController()->getAction()->getLayout()->getBlock('google_tag_manager');
23 | if ($block) $block->setOrderIds($orderIds);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/app/code/community/CVM/GoogleTagManager/etc/adminhtml.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | Google API
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/code/community/CVM/GoogleTagManager/etc/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 | 1.0.0
15 |
16 |
17 |
18 |
19 |
20 | CVM_GoogleTagManager_Block
21 |
22 |
23 |
24 |
25 | CVM_GoogleTagManager_Helper
26 |
27 |
28 |
29 |
30 | CVM_GoogleTagManager_Model
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | CVM_GoogleTagManager.csv
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | googletagmanager/observer
49 | setGoogleTagManagerTransactionData
50 |
51 |
52 |
53 |
54 |
55 |
56 | googletagmanager/observer
57 | setGoogleTagManagerTransactionData
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | googletagmanager.xml
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | CVM_GoogleTagManager.csv
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | 0
85 | 0
86 | 0
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/app/code/community/CVM/GoogleTagManager/etc/system.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | text
18 | 15
19 | 1
20 | 1
21 | 1
22 |
23 |
24 |
25 | select
26 | adminhtml/system_config_source_yesno
27 | 10
28 | 1
29 | 1
30 | 1
31 |
32 |
33 |
34 | text
35 | 20
36 | 1
37 | 1
38 | 1
39 | 1
40 |
41 |
42 |
43 | Populates GTM data layer with transaction data.
44 | select
45 | adminhtml/system_config_source_enabledisable
46 | 30
47 | 1
48 | 1
49 | 1
50 | 1
51 |
52 |
53 |
54 | Optional value for transactionType field.
55 | text
56 | 31
57 | 1
58 | 1
59 | 1
60 |
61 | 1
62 | 1
63 |
64 |
65 |
66 |
67 | Optional value for transactionAffiliation field.
68 | text
69 | 32
70 | 1
71 | 1
72 | 1
73 |
74 | 1
75 | 1
76 |
77 |
78 |
79 |
80 | Populates GTM data layer with visitor data.
81 | select
82 | adminhtml/system_config_source_enabledisable
83 | 40
84 | 1
85 | 1
86 | 1
87 | 1
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/app/design/frontend/base/default/layout/googletagmanager.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/design/frontend/base/default/template/googletagmanager/gtm.phtml:
--------------------------------------------------------------------------------
1 |
8 | * @copyright Copyright (c) 2013 Chris Martin
9 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License 3.0 (OSL-3.0)
10 | */
11 | ?>
12 |
13 | _getDataLayer();
16 |
17 | // Render the container snippet.
18 | echo $this->_getContainerSnippet();
19 | ?>
20 |
21 |
--------------------------------------------------------------------------------
/app/etc/modules/CVM_GoogleTagManager.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 | true
15 | community
16 |
17 |
18 |
--------------------------------------------------------------------------------