Version Notes
The first stable version of Metrilo's integration with Magento
Download this release
Release Info
Developer | Murry Ivanoff |
Extension | Metrilo_Analytics |
Version | 1.0.0 |
Comparing to | |
See all releases |
Version 1.0.0
- app/code/community/Metrilo/Analytics/Block/Adminhtml/System/Config/Form/Button.php +81 -0
- app/code/community/Metrilo/Analytics/Block/Head.php +39 -0
- app/code/community/Metrilo/Analytics/Helper/Data.php +230 -0
- app/code/community/Metrilo/Analytics/Model/Import.php +48 -0
- app/code/community/Metrilo/Analytics/Model/Observer.php +257 -0
- app/code/community/Metrilo/Analytics/controllers/Adminhtml/AjaxController.php +64 -0
- app/code/community/Metrilo/Analytics/etc/adminhtml.xml +23 -0
- app/code/community/Metrilo/Analytics/etc/config.xml +134 -0
- app/code/community/Metrilo/Analytics/etc/system.xml +82 -0
- app/design/adminhtml/default/default/layout/metrilo_analytics.xml +10 -0
- app/design/adminhtml/default/default/template/metrilo/system/config/button.phtml +57 -0
- app/etc/modules/Metrilo_Analytics.xml +9 -0
- package.xml +28 -0
- skin/adminhtml/default/default/metrilo/favicon-metrilo.png +0 -0
- skin/adminhtml/default/default/metrilo/loader.gif +0 -0
- skin/adminhtml/default/default/metrilo/logo.png +0 -0
- skin/adminhtml/default/default/metrilo/styles.css +41 -0
app/code/community/Metrilo/Analytics/Block/Adminhtml/System/Config/Form/Button.php
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Button widget class
|
4 |
+
* Add import model and render button view
|
5 |
+
*
|
6 |
+
* @author Miroslav Petrov <miro91tn@gmail.com>
|
7 |
+
*/
|
8 |
+
class Metrilo_Analytics_Block_Adminhtml_System_Config_Form_Button extends Mage_Adminhtml_Block_System_Config_Form_Field
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* Set template
|
12 |
+
*
|
13 |
+
* @return void
|
14 |
+
*/
|
15 |
+
protected function _construct()
|
16 |
+
{
|
17 |
+
parent::_construct();
|
18 |
+
$this->setTemplate('metrilo/system/config/button.phtml');
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Get import instance
|
23 |
+
*
|
24 |
+
* @return Metrilo_Analytics_Model_Import
|
25 |
+
*/
|
26 |
+
public function getImport()
|
27 |
+
{
|
28 |
+
return Mage::getSingleton('metrilo_analytics/import');
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Render metrilo js if module is enabled
|
33 |
+
*
|
34 |
+
* @return string
|
35 |
+
*/
|
36 |
+
protected function _toHtml()
|
37 |
+
{
|
38 |
+
$html = parent::_toHtml();
|
39 |
+
$helper = Mage::helper('metrilo_analytics');
|
40 |
+
if($helper->isEnabled() && $helper->getApiToken() && $helper->getApiSecret())
|
41 |
+
return $html;
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Return element html
|
46 |
+
*
|
47 |
+
* @param Varien_Data_Form_Element_Abstract $element
|
48 |
+
* @return string
|
49 |
+
*/
|
50 |
+
protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
|
51 |
+
{
|
52 |
+
return $this->_toHtml();
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Return ajax url for button
|
57 |
+
*
|
58 |
+
* @return string
|
59 |
+
*/
|
60 |
+
public function getAjaxUrl()
|
61 |
+
{
|
62 |
+
return Mage::helper('adminhtml')->getUrl("metrilo_analytics/adminhtml_ajax", array('isAjax'=> true));
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Generate button html
|
67 |
+
*
|
68 |
+
* @return string
|
69 |
+
*/
|
70 |
+
public function getButtonHtml()
|
71 |
+
{
|
72 |
+
$button = $this->getLayout()->createBlock('adminhtml/widget_button')
|
73 |
+
->setData(array(
|
74 |
+
'id' => 'metrilo_button',
|
75 |
+
'label' => $this->helper('adminhtml')->__('Import orders'),
|
76 |
+
'onclick' => 'javascript:import_metrilo(); return false;'
|
77 |
+
));
|
78 |
+
|
79 |
+
return $button->toHtml();
|
80 |
+
}
|
81 |
+
}
|
app/code/community/Metrilo/Analytics/Block/Head.php
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Block for head part who render all js lines
|
4 |
+
*
|
5 |
+
* @author Miroslav Petrov <miro91tn@gmail.com>
|
6 |
+
*/
|
7 |
+
class Metrilo_Analytics_Block_Head extends Mage_Core_Block_Template
|
8 |
+
{
|
9 |
+
/**
|
10 |
+
* key in session storage
|
11 |
+
*/
|
12 |
+
const DATA_TAG = "metrilo_events";
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Get events to track them to metrilo js api
|
16 |
+
*
|
17 |
+
* @return array
|
18 |
+
*/
|
19 |
+
public function getEvents()
|
20 |
+
{
|
21 |
+
$helper = Mage::helper('metrilo_analytics');
|
22 |
+
$events = (array)Mage::getSingleton('core/session')->getData(self::DATA_TAG);
|
23 |
+
// clear events from session ater get events once
|
24 |
+
Mage::getSingleton('core/session')->setData(self::DATA_TAG,'');
|
25 |
+
return array_filter($events);
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Render metrilo js if module is enabled
|
30 |
+
*
|
31 |
+
* @return string
|
32 |
+
*/
|
33 |
+
protected function _toHtml()
|
34 |
+
{
|
35 |
+
$html = parent::_toHtml();
|
36 |
+
if(Mage::helper('metrilo_analytics')->isEnabled())
|
37 |
+
return $html;
|
38 |
+
}
|
39 |
+
}
|
app/code/community/Metrilo/Analytics/Helper/Data.php
ADDED
@@ -0,0 +1,230 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Helper class for metrilo properties
|
4 |
+
*
|
5 |
+
* @author Miroslav Petrov <miro91tn@gmail.com>
|
6 |
+
*/
|
7 |
+
class Metrilo_Analytics_Helper_Data extends Mage_Core_Helper_Abstract
|
8 |
+
{
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Get session instance
|
12 |
+
*
|
13 |
+
* @return Mage_Core_Model_Session
|
14 |
+
*/
|
15 |
+
public function getSession()
|
16 |
+
{
|
17 |
+
return Mage::getSingleton('core/session');
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Check if metrilo module is enabled
|
22 |
+
*
|
23 |
+
* @return boolean
|
24 |
+
*/
|
25 |
+
public function isEnabled()
|
26 |
+
{
|
27 |
+
return Mage::getStoreConfig('metrilo_analytics_settings/settings/enable');
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Get API Token from system configuration
|
32 |
+
*
|
33 |
+
* @return string
|
34 |
+
*/
|
35 |
+
public function getApiToken()
|
36 |
+
{
|
37 |
+
return Mage::getStoreConfig('metrilo_analytics_settings/settings/api_key');
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Get API Secret from system configuration
|
42 |
+
*
|
43 |
+
* @return string
|
44 |
+
*/
|
45 |
+
public function getApiSecret()
|
46 |
+
{
|
47 |
+
return Mage::getStoreConfig('metrilo_analytics_settings/settings/api_secret');
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Add event to queue
|
52 |
+
*
|
53 |
+
* @param string $method Can be identiy|track
|
54 |
+
* @param string $type
|
55 |
+
* @param string|array $data
|
56 |
+
*/
|
57 |
+
public function addEvent($method, $type, $data)
|
58 |
+
{
|
59 |
+
$events = (array)$this->getSession()->getData(Metrilo_Analytics_Block_Head::DATA_TAG);
|
60 |
+
$events[] = array(
|
61 |
+
'method' => $method,
|
62 |
+
'type' => $type,
|
63 |
+
'data' => $data
|
64 |
+
);
|
65 |
+
$this->getSession()->setData(Metrilo_Analytics_Block_Head::DATA_TAG, $events);
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Get order details and sort them for metrilo
|
70 |
+
*
|
71 |
+
* @param Mage_Sales_Model_Order $order
|
72 |
+
* @return array
|
73 |
+
*/
|
74 |
+
public function prepareOrderDetails($order)
|
75 |
+
{
|
76 |
+
$data = array(
|
77 |
+
'order_id' => $order->getIncrementId(),
|
78 |
+
'order_status' => $order->getStatus(),
|
79 |
+
'amount' => (float)$order->getGrandTotal(),
|
80 |
+
'shipping_amount' => (float)$order->getShippingAmount(),
|
81 |
+
'tax_amount' => $order->getTaxAmount(),
|
82 |
+
'items' => array(),
|
83 |
+
'shipping_method' => $order->getShippingDescription(),
|
84 |
+
'payment_method' => $order->getPayment()->getMethodInstance()->getTitle(),
|
85 |
+
);
|
86 |
+
|
87 |
+
if ($order->getCouponCode()) {
|
88 |
+
$data['coupons'] = $order->getCouponCode();
|
89 |
+
}
|
90 |
+
$skusAdded = array();
|
91 |
+
foreach ($order->getAllItems() as $item) {
|
92 |
+
if (in_array($item->getSku(), $skusAdded)) continue;
|
93 |
+
|
94 |
+
$skusAdded[] = $item->getSku();
|
95 |
+
$dataItem = array(
|
96 |
+
'id' => $item->getProductId(),
|
97 |
+
'price' => (float)$item->getPrice() ? $item->getPrice() : $item->getProduct()->getFinalPrice(),
|
98 |
+
'name' => $item->getName(),
|
99 |
+
'url' => $item->getProduct()->getProductUrl(),
|
100 |
+
'quantity' => (int)$item->getQtyOrdered()
|
101 |
+
);
|
102 |
+
if ($item->getProductType() == 'configurable' || $item->getProductType() == 'grouped') {
|
103 |
+
if ($item->getProductType() == 'grouped') {
|
104 |
+
$parentIds = Mage::getModel('catalog/product_type_grouped')->getParentIdsByChild($item->getProductId());
|
105 |
+
$parentId = $parentIds[0];
|
106 |
+
} else {
|
107 |
+
$parentId = $item->getProductId();
|
108 |
+
}
|
109 |
+
$mainProduct = Mage::getModel('catalog/product')->load($parentId);
|
110 |
+
$dataItem['id'] = $mainProduct->getId();
|
111 |
+
$dataItem['name'] = $mainProduct->getName();
|
112 |
+
$dataItem['url'] = $mainProduct->getProductUrl();
|
113 |
+
$dataItem['option_id'] = $item->getSku();
|
114 |
+
$dataItem['option_name'] = trim(str_replace("-", " ", $item->getName()));
|
115 |
+
$dataItem['option_price'] = (float)$item->getPrice();
|
116 |
+
}
|
117 |
+
$data['items'][] = $dataItem;
|
118 |
+
}
|
119 |
+
return $data;
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Create HTTP request to metrilo server
|
124 |
+
*
|
125 |
+
* @param string $ident
|
126 |
+
* @param string $event
|
127 |
+
* @param array $params
|
128 |
+
* @param boolean|array $identityData
|
129 |
+
* @param boolean|int $time
|
130 |
+
* @param boolean|array $callParameters
|
131 |
+
* @return void
|
132 |
+
*/
|
133 |
+
public function callApi($ident, $event, $params, $identityData = false, $time = false, $callParameters = false)
|
134 |
+
{
|
135 |
+
try {
|
136 |
+
$call = $this->buildEventArray($ident, $event, $params, $identityData, $time, $callParameters);
|
137 |
+
// We should handle the setting of token parameter, as it's part of the request
|
138 |
+
$call['token'] = $this->getApiToken();
|
139 |
+
|
140 |
+
// Additional ksort here because of adding token param
|
141 |
+
ksort($call);
|
142 |
+
$basedCall = base64_encode(Mage::helper('core')->jsonEncode($call));
|
143 |
+
$signature = md5($basedCall.$this->getApiSecret());
|
144 |
+
// Use Varien_Http_Client
|
145 |
+
// to generate API call end point and call it
|
146 |
+
$url = 'http://p.metrilo.com/t?s='.$signature.'&hs='.$basedCall;
|
147 |
+
$client = new Varien_Http_Client($url);
|
148 |
+
$response = $client->request();
|
149 |
+
$result = Mage::helper('core')->jsonDecode($response->getBody());
|
150 |
+
if (!$result['status']) {
|
151 |
+
Mage::log($result['error'], null, 'Metrilo_Analytics.log');
|
152 |
+
}
|
153 |
+
} catch (Exception $e){
|
154 |
+
Mage::log($e->getMessage(), null, 'Metrilo_Analytics.log');
|
155 |
+
}
|
156 |
+
}
|
157 |
+
|
158 |
+
public function callBatchApi($ordersForSubmition)
|
159 |
+
{
|
160 |
+
try {
|
161 |
+
// Consider token is in the first level in the hashed json
|
162 |
+
$call = array(
|
163 |
+
'token' => $this->getApiToken(),
|
164 |
+
'events' => $ordersForSubmition
|
165 |
+
);
|
166 |
+
|
167 |
+
// Additional ksort here because of adding token param
|
168 |
+
ksort($call);
|
169 |
+
|
170 |
+
$basedCall = base64_encode(Mage::helper('core')->jsonEncode($call));
|
171 |
+
$signature = md5($basedCall.$this->getApiSecret());
|
172 |
+
|
173 |
+
$url = 'http://p.metrilo.com/bt';
|
174 |
+
$client = new Varien_Http_Client($url);
|
175 |
+
|
176 |
+
$requestBody = array(
|
177 |
+
's' => $signature,
|
178 |
+
'hs' => $basedCall
|
179 |
+
);
|
180 |
+
// This method supports passing named array as well as key, value
|
181 |
+
$client->setParameterPost($requestBody);
|
182 |
+
$response = $client->request('POST');
|
183 |
+
|
184 |
+
if ($response->isError()) {
|
185 |
+
Mage::log($response->getBody(), null, 'Metrilo_Analytics.log');
|
186 |
+
}
|
187 |
+
} catch (Exception $e) {
|
188 |
+
Mage::log($e->getMessage(), null, 'Metrilo_Analytics.log');
|
189 |
+
}
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Build event array ready for encoding and encrypting. Built array is returned using ksort.
|
194 |
+
*
|
195 |
+
* @param string $ident
|
196 |
+
* @param string $event
|
197 |
+
* @param array $params
|
198 |
+
* @param boolean|array $identityData
|
199 |
+
* @param boolean|int $time
|
200 |
+
* @param boolean|array $callParameters
|
201 |
+
* @return void
|
202 |
+
*/
|
203 |
+
public function buildEventArray($ident, $event, $params, $identityData = false, $time = false, $callParameters = false)
|
204 |
+
{
|
205 |
+
$call = array(
|
206 |
+
'event_type' => $event,
|
207 |
+
'params' => $params,
|
208 |
+
'uid' => $ident
|
209 |
+
);
|
210 |
+
if($time) {
|
211 |
+
$call['time'] = $time;
|
212 |
+
}
|
213 |
+
|
214 |
+
// check for special parameters to include in the API call
|
215 |
+
if($callParameters) {
|
216 |
+
if($callParameters['use_ip']) {
|
217 |
+
$call['use_ip'] = $callParameters['use_ip'];
|
218 |
+
}
|
219 |
+
}
|
220 |
+
// put identity data in call if available
|
221 |
+
if($identityData) {
|
222 |
+
$call['identity'] = $identityData;
|
223 |
+
}
|
224 |
+
|
225 |
+
// Prepare keys is alphabetical order
|
226 |
+
ksort($call);
|
227 |
+
|
228 |
+
return $call;
|
229 |
+
}
|
230 |
+
}
|
app/code/community/Metrilo/Analytics/Model/Import.php
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Import model which collect all previous orders
|
4 |
+
*
|
5 |
+
* @author Miroslav Petrov <miro91tn@gmail.com>
|
6 |
+
*/
|
7 |
+
class Metrilo_Analytics_Model_Import extends Mage_Core_Model_Abstract
|
8 |
+
{
|
9 |
+
private $_ordersTotal = 0;
|
10 |
+
private $_totalChunks = 0;
|
11 |
+
private $_chunkItems = 15;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Prepare all order ids
|
15 |
+
*
|
16 |
+
* @return void
|
17 |
+
*/
|
18 |
+
public function _construct()
|
19 |
+
{
|
20 |
+
// prepare to fetch all orders
|
21 |
+
$this->_ordersTotal = Mage::getModel('sales/order')->getCollection()->getSize();
|
22 |
+
$this->_totalChunks = (int)ceil($this->_ordersTotal / $this->_chunkItems);
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Get chunk orders
|
27 |
+
*
|
28 |
+
* @param int
|
29 |
+
* @return Varien_Data_Collection
|
30 |
+
*/
|
31 |
+
public function getOrders($chunkId)
|
32 |
+
{
|
33 |
+
return Mage::getModel('sales/order')
|
34 |
+
->getCollection()
|
35 |
+
->setPageSize($this->_chunkItems)
|
36 |
+
->setCurPage($chunkId + 1);
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Chenks array
|
41 |
+
*
|
42 |
+
* @return array
|
43 |
+
*/
|
44 |
+
public function getChunks()
|
45 |
+
{
|
46 |
+
return $this->_totalChunks;
|
47 |
+
}
|
48 |
+
}
|
app/code/community/Metrilo/Analytics/Model/Observer.php
ADDED
@@ -0,0 +1,257 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Catch events and track them to metrilo api
|
4 |
+
*
|
5 |
+
* @author Miroslav Petrov <miro91tn@gmail.com>
|
6 |
+
*/
|
7 |
+
class Metrilo_Analytics_Model_Observer
|
8 |
+
{
|
9 |
+
/**
|
10 |
+
* Identify customer after login
|
11 |
+
*
|
12 |
+
* @param Varien_Event_Observer $observer
|
13 |
+
* @return void
|
14 |
+
*/
|
15 |
+
public function customerLogin(Varien_Event_Observer $observer)
|
16 |
+
{
|
17 |
+
$helper = Mage::helper('metrilo_analytics');
|
18 |
+
$customer = $observer->getEvent()->getCustomer();
|
19 |
+
$data = array(
|
20 |
+
'id' => $customer->getId(),
|
21 |
+
'params' => array(
|
22 |
+
'email' => $customer->getEmail(),
|
23 |
+
'name' => $customer->getName(),
|
24 |
+
'first_name' => $customer->getFirstname(),
|
25 |
+
'last_name' => $customer->getLastname(),
|
26 |
+
)
|
27 |
+
);
|
28 |
+
$helper->addEvent('identify', 'identify', $data);
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Track page views
|
33 |
+
* - homepage & CMS pages
|
34 |
+
* - product view pages
|
35 |
+
* - category view pages
|
36 |
+
* - cart view
|
37 |
+
* - checkout
|
38 |
+
* - any other pages (get title from head)
|
39 |
+
*
|
40 |
+
* @param Varien_Event_Observer $observer
|
41 |
+
* @return void
|
42 |
+
*/
|
43 |
+
public function trackPageView(Varien_Event_Observer $observer)
|
44 |
+
{
|
45 |
+
$helper = Mage::helper('metrilo_analytics');
|
46 |
+
$action = $observer->getEvent()->getAction()->getFullActionName();
|
47 |
+
$pageTracked = false;
|
48 |
+
// homepage & CMS pages
|
49 |
+
if ($action == 'cms_index_index' || $action == 'cms_page_view') {
|
50 |
+
$title = Mage::getSingleton('cms/page')->getTitle();
|
51 |
+
$helper->addEvent('track', 'pageview', $title);
|
52 |
+
$pageTracked = true;
|
53 |
+
}
|
54 |
+
// category view pages
|
55 |
+
if($action == 'catalog_category_view') {
|
56 |
+
$category = Mage::registry('current_category');
|
57 |
+
$data = array(
|
58 |
+
'id' => $category->getId(),
|
59 |
+
'name' => $category->getName()
|
60 |
+
);
|
61 |
+
$helper->addEvent('track', 'view_category', $data);
|
62 |
+
$pageTracked = true;
|
63 |
+
}
|
64 |
+
// product view pages
|
65 |
+
if ($action == 'catalog_product_view') {
|
66 |
+
$product = Mage::registry('current_product');
|
67 |
+
$data = array(
|
68 |
+
'id' => $product->getId(),
|
69 |
+
'name' => $product->getName(),
|
70 |
+
'price' => $product->getFinalPrice(),
|
71 |
+
'url' => $product->getProductUrl()
|
72 |
+
);
|
73 |
+
// Additional information ( image and categories )
|
74 |
+
if($product->getImage())
|
75 |
+
$data['image_url'] = (string)Mage::helper('catalog/image')->init($product, 'image');
|
76 |
+
|
77 |
+
if(count($product->getCategoryIds())) {
|
78 |
+
$categories = array();
|
79 |
+
$collection = $product->getCategoryCollection()->addAttributeToSelect('*');
|
80 |
+
foreach ($collection as $category) {
|
81 |
+
$categories[] = array(
|
82 |
+
'id' => $category->getId(),
|
83 |
+
'name' => $category->getName()
|
84 |
+
);
|
85 |
+
}
|
86 |
+
$data['categories'] = $categories;
|
87 |
+
}
|
88 |
+
$helper->addEvent('track', 'view_product', $data);
|
89 |
+
$pageTracked = true;
|
90 |
+
}
|
91 |
+
// cart view
|
92 |
+
if($action == 'checkout_cart_index') {
|
93 |
+
$helper->addEvent('track', 'view_cart', array());
|
94 |
+
$pageTracked = true;
|
95 |
+
}
|
96 |
+
// checkout
|
97 |
+
if ($action != 'checkout_cart_index' && strpos($action, 'checkout') !== false && strpos($action, 'success') === false) {
|
98 |
+
$helper->addEvent('track', 'checkout_start', array());
|
99 |
+
$pageTracked = true;
|
100 |
+
}
|
101 |
+
// Any other pages
|
102 |
+
if(!$pageTracked) {
|
103 |
+
$title = $observer->getEvent()->getLayout()->getBlock('head')->getTitle();
|
104 |
+
$helper->addEvent('track', 'pageview', $title);
|
105 |
+
}
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Event for adding product to cart
|
110 |
+
* "checkout_cart_product_add_after"
|
111 |
+
*
|
112 |
+
* @param Varien_Event_Observer $observer [description]
|
113 |
+
*/
|
114 |
+
public function addToCart(Varien_Event_Observer $observer)
|
115 |
+
{
|
116 |
+
/**
|
117 |
+
* @var Mage_Sales_Model_Quote_Item
|
118 |
+
*/
|
119 |
+
$item = $observer->getQuoteItem();
|
120 |
+
$product = $item->getProduct();
|
121 |
+
$cartProduct = $observer->getProduct();
|
122 |
+
|
123 |
+
if ($cartProduct->isGrouped()) {
|
124 |
+
$options = Mage::app()->getRequest()->getParam('super_group');
|
125 |
+
if (is_array($options)) {
|
126 |
+
foreach ($options as $productId => $qty) {
|
127 |
+
$this->_addToCart((int)$productId, $cartProduct, (int)$qty);
|
128 |
+
}
|
129 |
+
}
|
130 |
+
} elseif($cartProduct->isConfigurable()) {
|
131 |
+
$this->_addToCart($product->getId(), $cartProduct, $item->getQty());
|
132 |
+
} else {
|
133 |
+
$this->_addToCart($cartProduct->getId(), $cartProduct, $item->getQty());
|
134 |
+
}
|
135 |
+
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Add to cart event
|
140 |
+
*
|
141 |
+
* @param integer $productId
|
142 |
+
* @param Mage_Catalog_Model_Product $item
|
143 |
+
* @param integer $qty
|
144 |
+
*/
|
145 |
+
private function _addToCart($productId, $item, $qty) {
|
146 |
+
$helper = Mage::helper('metrilo_analytics');
|
147 |
+
$product = Mage::getModel('catalog/product')->load($productId);
|
148 |
+
|
149 |
+
$data = array(
|
150 |
+
'id' => (int)$product->getId(),
|
151 |
+
'price' => (float)$product->getFinalPrice(),
|
152 |
+
'name' => $product->getName(),
|
153 |
+
'url' => $product->getProductUrl(),
|
154 |
+
'quantity' => $qty
|
155 |
+
);
|
156 |
+
|
157 |
+
// Add options for grouped or configurable products
|
158 |
+
if ($item->isGrouped() || $item->isConfigurable()) {
|
159 |
+
$data['id'] = $item->getId();
|
160 |
+
$data['name'] = $item->getName();
|
161 |
+
$data['url'] = $item->getProductUrl();
|
162 |
+
// Options
|
163 |
+
$data['option_id'] = $product->getSku();
|
164 |
+
$data['option_name'] = trim(str_replace("-", " ", $product->getName()));
|
165 |
+
$data['option_price'] = (float)$product->getFinalPrice();
|
166 |
+
}
|
167 |
+
|
168 |
+
$helper->addEvent('track', 'add_to_cart', $data);
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* Event for removing item from shopping bag
|
173 |
+
*
|
174 |
+
* @param Varien_Event_Observer $observer
|
175 |
+
* @return void
|
176 |
+
*/
|
177 |
+
public function removeFromCart(Varien_Event_Observer $observer)
|
178 |
+
{
|
179 |
+
$helper = Mage::helper('metrilo_analytics');
|
180 |
+
$item = $observer->getQuoteItem();
|
181 |
+
$product = $item->getProduct();
|
182 |
+
|
183 |
+
$data = array(
|
184 |
+
'id' => $product->getId()
|
185 |
+
);
|
186 |
+
|
187 |
+
$helper->addEvent('track', 'remove_from_cart', $data);
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* Track placing a new order from customer
|
192 |
+
*
|
193 |
+
* @param Varien_Event_Observer $observer
|
194 |
+
* @return void
|
195 |
+
*/
|
196 |
+
public function trackNewOrder(Varien_Event_Observer $observer)
|
197 |
+
{
|
198 |
+
$helper = Mage::helper('metrilo_analytics');
|
199 |
+
$data = array();
|
200 |
+
$order = $observer->getOrder();
|
201 |
+
if ($order->getId()) {
|
202 |
+
$data = $helper->prepareOrderDetails($order);
|
203 |
+
$helper->addEvent('track', 'order', $data);
|
204 |
+
}
|
205 |
+
}
|
206 |
+
|
207 |
+
/**
|
208 |
+
* Track adding discount codes in shopping bag
|
209 |
+
*
|
210 |
+
* @param Varien_Event_Observer $observer
|
211 |
+
* @return void
|
212 |
+
*/
|
213 |
+
public function trackCoupon(Varien_Event_Observer $observer)
|
214 |
+
{
|
215 |
+
$helper = Mage::helper('metrilo_analytics');
|
216 |
+
$code = Mage::getSingleton('checkout/cart')->getQuote()->getCouponCode();
|
217 |
+
if (strlen($code)) {
|
218 |
+
$helper->addEvent('track', 'applied_coupon', $code);
|
219 |
+
}
|
220 |
+
}
|
221 |
+
|
222 |
+
/**
|
223 |
+
* Send order information after save
|
224 |
+
*
|
225 |
+
* @param Varien_Event_Observer $observer
|
226 |
+
* @return void
|
227 |
+
*/
|
228 |
+
public function updateOrder(Varien_Event_Observer $observer)
|
229 |
+
{
|
230 |
+
$helper = Mage::helper('metrilo_analytics');
|
231 |
+
$order = $observer->getOrder();
|
232 |
+
$orderDetails = $helper->prepareOrderDetails($order);
|
233 |
+
|
234 |
+
$callParameters = false;
|
235 |
+
|
236 |
+
// check if order has customer IP in it
|
237 |
+
$ip = $order->getRemoteIp();
|
238 |
+
if ($ip){
|
239 |
+
$callParameters = array('use_ip' => $ip);
|
240 |
+
}
|
241 |
+
|
242 |
+
$time = false;
|
243 |
+
if ($order->getCreatedAtStoreDate()) {
|
244 |
+
$time = $order->getCreatedAtStoreDate()->getTimestamp() * 1000;
|
245 |
+
}
|
246 |
+
|
247 |
+
$identityData = array(
|
248 |
+
'email' => $order->getCustomerEmail(),
|
249 |
+
'first_name' => $order->getBillingAddress()->getFirstname(),
|
250 |
+
'last_name' => $order->getBillingAddress()->getLastname(),
|
251 |
+
'name' => $order->getBillingAddress()->getName(),
|
252 |
+
);
|
253 |
+
|
254 |
+
$helper->callApi($identityData['email'], 'order', $orderDetails, $identityData, $time, $callParameters);
|
255 |
+
}
|
256 |
+
|
257 |
+
}
|
app/code/community/Metrilo/Analytics/controllers/Adminhtml/AjaxController.php
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Ajax controller for sending orders to metrilo
|
4 |
+
*
|
5 |
+
* @author Miroslav Petrov <miro91tn@gmail.com>
|
6 |
+
*/
|
7 |
+
class Metrilo_Analytics_Adminhtml_AjaxController extends Mage_Adminhtml_Controller_Action
|
8 |
+
{
|
9 |
+
/**
|
10 |
+
* Import order chunks
|
11 |
+
*
|
12 |
+
* @return void
|
13 |
+
*/
|
14 |
+
public function indexAction()
|
15 |
+
{
|
16 |
+
$result = array();
|
17 |
+
$result['success'] = false;
|
18 |
+
$helper = Mage::helper('metrilo_analytics');
|
19 |
+
try {
|
20 |
+
$import = Mage::getSingleton('metrilo_analytics/import');
|
21 |
+
$chunkId = (int)$this->getRequest()->getParam('chunk_id');
|
22 |
+
$orders = $import->getOrders($chunkId);
|
23 |
+
$ordersForSubmition = array();
|
24 |
+
|
25 |
+
foreach ($orders as $order) {
|
26 |
+
if ($order->getId()) {
|
27 |
+
$orderDetails = $helper->prepareOrderDetails($order);
|
28 |
+
|
29 |
+
$callParameters = false;
|
30 |
+
|
31 |
+
// check if order has customer IP in it
|
32 |
+
$ip = $order->getRemoteIp();
|
33 |
+
if($ip){
|
34 |
+
$callParameters = array('use_ip' => $ip);
|
35 |
+
}
|
36 |
+
|
37 |
+
$time = false;
|
38 |
+
if ($order->getCreatedAtStoreDate()) {
|
39 |
+
$time = $order->getCreatedAtStoreDate()->getTimestamp() * 1000;
|
40 |
+
}
|
41 |
+
|
42 |
+
$identityData = array(
|
43 |
+
'email' => $order->getCustomerEmail(),
|
44 |
+
'first_name' => $order->getBillingAddress()->getFirstname(),
|
45 |
+
'last_name' => $order->getBillingAddress()->getLastname(),
|
46 |
+
'name' => $order->getBillingAddress()->getName(),
|
47 |
+
);
|
48 |
+
|
49 |
+
$builtEventArray = $helper->buildEventArray(
|
50 |
+
$identityData['email'], 'order', $orderDetails, $identityData, $time, $callParameters
|
51 |
+
);
|
52 |
+
|
53 |
+
array_push($ordersForSubmition, $builtEventArray);
|
54 |
+
}
|
55 |
+
}
|
56 |
+
|
57 |
+
$helper->callBatchApi($ordersForSubmition);
|
58 |
+
$result['success'] = true;
|
59 |
+
} catch (Exception $e) {
|
60 |
+
Mage::logException($e);
|
61 |
+
}
|
62 |
+
$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
|
63 |
+
}
|
64 |
+
}
|
app/code/community/Metrilo/Analytics/etc/adminhtml.xml
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
|
3 |
+
<config>
|
4 |
+
<acl>
|
5 |
+
<resources>
|
6 |
+
<admin>
|
7 |
+
<children>
|
8 |
+
<system>
|
9 |
+
<children>
|
10 |
+
<config>
|
11 |
+
<children>
|
12 |
+
<metrilo_analytics_settings>
|
13 |
+
<title>Metrilo Settings Tab</title>
|
14 |
+
</metrilo_analytics_settings>
|
15 |
+
</children>
|
16 |
+
</config>
|
17 |
+
</children>
|
18 |
+
</system>
|
19 |
+
</children>
|
20 |
+
</admin>
|
21 |
+
</resources>
|
22 |
+
</acl>
|
23 |
+
</config>
|
app/code/community/Metrilo/Analytics/etc/config.xml
ADDED
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<!--
|
3 |
+
/**
|
4 |
+
* @package Metrilo_Analytics
|
5 |
+
* @author Miroslav Petrov <miro91tn@gmail.com>
|
6 |
+
*/
|
7 |
+
-->
|
8 |
+
<config>
|
9 |
+
<modules>
|
10 |
+
<Metrilo_Analytics>
|
11 |
+
<version>1.0.0</version>
|
12 |
+
</Metrilo_Analytics>
|
13 |
+
</modules>
|
14 |
+
<frontend>
|
15 |
+
<layout>
|
16 |
+
<updates>
|
17 |
+
<metrilo_analytics>
|
18 |
+
<file>metrilo_analytics.xml</file>
|
19 |
+
</metrilo_analytics>
|
20 |
+
</updates>
|
21 |
+
</layout>
|
22 |
+
<events>
|
23 |
+
<customer_login>
|
24 |
+
<observers>
|
25 |
+
<metrilo_login>
|
26 |
+
<type>singleton</type>
|
27 |
+
<class>Metrilo_Analytics_Model_Observer</class>
|
28 |
+
<method>customerLogin</method>
|
29 |
+
</metrilo_login>
|
30 |
+
</observers>
|
31 |
+
</customer_login>
|
32 |
+
<controller_action_layout_generate_blocks_after>
|
33 |
+
<observers>
|
34 |
+
<page_view>
|
35 |
+
<type>singleton</type>
|
36 |
+
<class>Metrilo_Analytics_Model_Observer</class>
|
37 |
+
<method>trackPageView</method>
|
38 |
+
</page_view>
|
39 |
+
</observers>
|
40 |
+
</controller_action_layout_generate_blocks_after>
|
41 |
+
<checkout_cart_product_add_after>
|
42 |
+
<observers>
|
43 |
+
<add_to_cart>
|
44 |
+
<type>singleton</type>
|
45 |
+
<class>Metrilo_Analytics_Model_Observer</class>
|
46 |
+
<method>addToCart</method>
|
47 |
+
</add_to_cart>
|
48 |
+
</observers>
|
49 |
+
</checkout_cart_product_add_after>
|
50 |
+
<sales_quote_remove_item>
|
51 |
+
<observers>
|
52 |
+
<remove_from_cart>
|
53 |
+
<type>singleton</type>
|
54 |
+
<class>Metrilo_Analytics_Model_Observer</class>
|
55 |
+
<method>removeFromCart</method>
|
56 |
+
</remove_from_cart>
|
57 |
+
</observers>
|
58 |
+
</sales_quote_remove_item>
|
59 |
+
<sales_order_place_after>
|
60 |
+
<observers>
|
61 |
+
<place_order>
|
62 |
+
<type>singleton</type>
|
63 |
+
<class>Metrilo_Analytics_Model_Observer</class>
|
64 |
+
<method>trackNewOrder</method>
|
65 |
+
</place_order>
|
66 |
+
</observers>
|
67 |
+
</sales_order_place_after>
|
68 |
+
<controller_action_postdispatch_checkout_cart_couponPost>
|
69 |
+
<observers>
|
70 |
+
<applied_coupon>
|
71 |
+
<type>singleton</type>
|
72 |
+
<class>Metrilo_Analytics_Model_Observer</class>
|
73 |
+
<method>trackCoupon</method>
|
74 |
+
</applied_coupon>
|
75 |
+
</observers>
|
76 |
+
</controller_action_postdispatch_checkout_cart_couponPost>
|
77 |
+
</events>
|
78 |
+
</frontend>
|
79 |
+
<global>
|
80 |
+
<events>
|
81 |
+
<sales_order_save_after>
|
82 |
+
<observers>
|
83 |
+
<update_order>
|
84 |
+
<type>singleton</type>
|
85 |
+
<class>Metrilo_Analytics_Model_Observer</class>
|
86 |
+
<method>updateOrder</method>
|
87 |
+
</update_order>
|
88 |
+
</observers>
|
89 |
+
</sales_order_save_after>
|
90 |
+
</events>
|
91 |
+
<models>
|
92 |
+
<metrilo_analytics>
|
93 |
+
<class>Metrilo_Analytics_Model</class>
|
94 |
+
</metrilo_analytics>
|
95 |
+
</models>
|
96 |
+
<blocks>
|
97 |
+
<metrilo_analytics>
|
98 |
+
<class>Metrilo_Analytics_Block</class>
|
99 |
+
</metrilo_analytics>
|
100 |
+
</blocks>
|
101 |
+
<helpers>
|
102 |
+
<metrilo_analytics>
|
103 |
+
<class>Metrilo_Analytics_Helper</class>
|
104 |
+
</metrilo_analytics>
|
105 |
+
</helpers>
|
106 |
+
</global>
|
107 |
+
<admin>
|
108 |
+
<routers>
|
109 |
+
<metrilo_analytics>
|
110 |
+
<use>admin</use>
|
111 |
+
<args>
|
112 |
+
<module>Metrilo_Analytics</module>
|
113 |
+
<frontName>metrilo_analytics</frontName>
|
114 |
+
</args>
|
115 |
+
</metrilo_analytics>
|
116 |
+
</routers>
|
117 |
+
</admin>
|
118 |
+
<adminhtml>
|
119 |
+
<layout>
|
120 |
+
<updates>
|
121 |
+
<metrilo_analytics>
|
122 |
+
<file>metrilo_analytics.xml</file>
|
123 |
+
</metrilo_analytics>
|
124 |
+
</updates>
|
125 |
+
</layout>
|
126 |
+
</adminhtml>
|
127 |
+
<default>
|
128 |
+
<metrilo_analytics_settings>
|
129 |
+
<settings>
|
130 |
+
<enable>0</enable>
|
131 |
+
</settings>
|
132 |
+
</metrilo_analytics_settings>
|
133 |
+
</default>
|
134 |
+
</config>
|
app/code/community/Metrilo/Analytics/etc/system.xml
ADDED
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<config>
|
3 |
+
<tabs>
|
4 |
+
<metrilo_analytics translate="label" module="metrilo_analytics">
|
5 |
+
<label>Metrilo Analytics</label>
|
6 |
+
<sort_order>100</sort_order>
|
7 |
+
</metrilo_analytics>
|
8 |
+
</tabs>
|
9 |
+
<sections>
|
10 |
+
<metrilo_analytics_settings module="metrilo_analytics">
|
11 |
+
<label>General Settings</label>
|
12 |
+
<class>metrilo-section</class>
|
13 |
+
<header_css>metrilo-header</header_css>
|
14 |
+
<sort_order>10</sort_order>
|
15 |
+
<show_in_default>1</show_in_default>
|
16 |
+
<show_in_website>1</show_in_website>
|
17 |
+
<show_in_store>1</show_in_store>
|
18 |
+
<tab>metrilo_analytics</tab>
|
19 |
+
<groups>
|
20 |
+
<settings>
|
21 |
+
<label>General settings</label>
|
22 |
+
<sort_order>10</sort_order>
|
23 |
+
<show_in_default>1</show_in_default>
|
24 |
+
<show_in_website>1</show_in_website>
|
25 |
+
<show_in_store>1</show_in_store>
|
26 |
+
<comment>
|
27 |
+
<![CDATA[
|
28 |
+
<div id="metrilo-info">
|
29 |
+
<img src="/skin/adminhtml/default/default/metrilo/favicon-metrilo.png" alt="Metrilo" />
|
30 |
+
<div class="text">
|
31 |
+
This module was developed by <a href="http://metrilo.com" target="_blank">Metrilo.com</a><br />
|
32 |
+
If you encounter any issues, let us know at <a href="mailto:support@metrilo.com">support@metrilo.com</a>. We'll be happy to assist you!
|
33 |
+
</div>
|
34 |
+
</div>
|
35 |
+
<div style="clear:both;"></div>
|
36 |
+
]]>
|
37 |
+
</comment>
|
38 |
+
<fields>
|
39 |
+
<enable>
|
40 |
+
<label>Enabled</label>
|
41 |
+
<frontend_type>select</frontend_type>
|
42 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
43 |
+
<sort_order>0</sort_order>
|
44 |
+
<show_in_default>1</show_in_default>
|
45 |
+
<show_in_website>1</show_in_website>
|
46 |
+
<show_in_store>1</show_in_store>
|
47 |
+
</enable>
|
48 |
+
<api_key>
|
49 |
+
<label>API Token</label>
|
50 |
+
<frontend_type>text</frontend_type>
|
51 |
+
<sort_order>10</sort_order>
|
52 |
+
<show_in_default>1</show_in_default>
|
53 |
+
<show_in_website>1</show_in_website>
|
54 |
+
<show_in_store>1</show_in_store>
|
55 |
+
<depends><enable>1</enable></depends>
|
56 |
+
</api_key>
|
57 |
+
<api_secret>
|
58 |
+
<label>API Secret</label>
|
59 |
+
<frontend_type>text</frontend_type>
|
60 |
+
<sort_order>20</sort_order>
|
61 |
+
<show_in_default>1</show_in_default>
|
62 |
+
<show_in_website>1</show_in_website>
|
63 |
+
<show_in_store>1</show_in_store>
|
64 |
+
<depends><enable>1</enable></depends>
|
65 |
+
</api_secret>
|
66 |
+
<import translate="label">
|
67 |
+
<label>Import orders</label>
|
68 |
+
<frontend_type>button</frontend_type>
|
69 |
+
<frontend_model>metrilo_analytics/adminhtml_system_config_form_button</frontend_model>
|
70 |
+
<sort_order>40</sort_order>
|
71 |
+
<comment>First set API token and secret before import orders</comment>
|
72 |
+
<show_in_default>1</show_in_default>
|
73 |
+
<show_in_website>1</show_in_website>
|
74 |
+
<show_in_store>1</show_in_store>
|
75 |
+
<depends><enable>1</enable></depends>
|
76 |
+
</import>
|
77 |
+
</fields>
|
78 |
+
</settings>
|
79 |
+
</groups>
|
80 |
+
</metrilo_analytics_settings>
|
81 |
+
</sections>
|
82 |
+
</config>
|
app/design/adminhtml/default/default/layout/metrilo_analytics.xml
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<layout>
|
3 |
+
|
4 |
+
<adminhtml_system_config_edit>
|
5 |
+
<reference name="head">
|
6 |
+
<action method="addCss"><stylesheet>metrilo/styles.css</stylesheet></action>
|
7 |
+
</reference>
|
8 |
+
</adminhtml_system_config_edit>
|
9 |
+
|
10 |
+
</layout>
|
app/design/adminhtml/default/default/template/metrilo/system/config/button.phtml
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php $import = $this->getImport(); ?>
|
2 |
+
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
|
3 |
+
<script type="text/javascript">
|
4 |
+
jQuery.noConflict();
|
5 |
+
|
6 |
+
function import_metrilo() {
|
7 |
+
var total_chunks = <?php echo $import->getChunks(); ?>;
|
8 |
+
var chunk_percentage = 100;
|
9 |
+
if(total_chunks > 0){
|
10 |
+
var chunk_percentage = (100 / total_chunks);
|
11 |
+
}
|
12 |
+
// Update button state and text
|
13 |
+
jQuery('#metrilo_button').addClass('disabled').attr('disabled', 'disabled').text('Importing orders');
|
14 |
+
|
15 |
+
var sync_chunk = function(chunk_id){
|
16 |
+
progress_percents = Math.round(chunk_id * chunk_percentage);
|
17 |
+
update_importing_message('Please wait... '+progress_percents+'% done', true);
|
18 |
+
|
19 |
+
// add form_key for magento controller check
|
20 |
+
data = {'chunk_id': chunk_id, 'form_key': window.FORM_KEY};
|
21 |
+
jQuery.post('<?php echo $this->getAjaxUrl(); ?>', data, function(response) {
|
22 |
+
new_chunk_id = chunk_id + 1;
|
23 |
+
if(new_chunk_id < total_chunks){
|
24 |
+
setTimeout(function(){
|
25 |
+
sync_chunk(new_chunk_id);
|
26 |
+
}, 100);
|
27 |
+
}else{
|
28 |
+
update_importing_message("<span style='color: green;'>Done! Please expect up to 30 minutes for your historical data to appear in Metrilo.</span>", false);
|
29 |
+
jQuery('#metrilo_button').removeClass('disabled').addClass('success').text('Orders imported');
|
30 |
+
}
|
31 |
+
|
32 |
+
});
|
33 |
+
|
34 |
+
}
|
35 |
+
|
36 |
+
var update_importing_message = function(message, show_loader){
|
37 |
+
if (show_loader)
|
38 |
+
message = '<img src="<?php echo $this->getSkinUrl("metrilo/loader.gif"); ?>" />' + message;
|
39 |
+
jQuery('#metrilo_import_status').html(message);
|
40 |
+
}
|
41 |
+
sync_chunk(0);
|
42 |
+
}
|
43 |
+
</script>
|
44 |
+
|
45 |
+
<div style="float: left;">
|
46 |
+
<h3>Importing your orders and customers</h3>
|
47 |
+
<p>
|
48 |
+
This tool helps you sync all your orders and customers to Metrilo and can take <strong>up to 20 minutes</strong> to complete. <br />
|
49 |
+
It will not affect your website's performance at all since it sends your orders to your Metrilo account in small chunks. <br /><br />
|
50 |
+
Make sure to <strong>not close this page</strong> while importing. Coffee, maybe?
|
51 |
+
</p>
|
52 |
+
</div>
|
53 |
+
<div style="clear:both"></div>
|
54 |
+
<?php echo $this->getButtonHtml() ?>
|
55 |
+
<div style="clear:both"></div>
|
56 |
+
<div id="metrilo_import_status"></div>
|
57 |
+
<div style="clear:both"></div>
|
app/etc/modules/Metrilo_Analytics.xml
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Metrilo_Analytics>
|
5 |
+
<active>true</active>
|
6 |
+
<codePool>community</codePool>
|
7 |
+
</Metrilo_Analytics>
|
8 |
+
</modules>
|
9 |
+
</config>
|
package.xml
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<package>
|
3 |
+
<name>Metrilo_Analytics</name>
|
4 |
+
<version>1.0.0</version>
|
5 |
+
<stability>stable</stability>
|
6 |
+
<license>Apache Software License (ASL)</license>
|
7 |
+
<channel>community</channel>
|
8 |
+
<extends/>
|
9 |
+
<summary>Metrilo is simple, yet extremely powerful Customer Insights, CRM and Email Marketing product that turns your Magento data into insights to grow your business. Metrilo helps you know everything about your customers from their first touch with your Magento store to their latest purchase.</summary>
|
10 |
+
<description>Metrilo is simple, yet extremely powerful Customer Insights, CRM and Email Marketing product that turns your Magento data into insights to grow your business. Metrilo helps you know everything about your customers from their first touch with your Magento store to their latest purchase.
|
11 |
+

|
12 |
+
* Have all your customer data in one place.
|
13 |
+
* Identify cohorts of customers, cart abandoners or high-value spenders. Metrilo gets all your customer data in one place and makes it easy for you to get to know your biggest asset - your customers.
|
14 |
+
* More repeat purchases, just a few clicks away. Send targeted email messages in 3 easy steps.
|
15 |
+
* Metrilo tracks all important eCommerce metrics for you. Automatically.
|
16 |
+
* Optimize your acquisition channels
|
17 |
+
* Track product performance
|
18 |
+
* Powerful intelligence for your sales team
|
19 |
+
* With Metrilo, you have an amazing real-time overview of who's doing what on your eCommerce store.
|
20 |
+
* Metrilo automatically collects and analyzes your eCommerce data to use for your email campaigns.</description>
|
21 |
+
<notes>The first stable version of Metrilo's integration with Magento</notes>
|
22 |
+
<authors><author><name>Murry Ivanoff</name><user>Metrilo</user><email>murry@metrilo.com</email></author><author><name>Miroslav Petrov</name><user>miro</user><email>miro91tn@gmail.com</email></author><author><name>Zhivko Draganov</name><user>zhivko</user><email>zhivko@metrilo.com</email></author></authors>
|
23 |
+
<date>2015-09-03</date>
|
24 |
+
<time>08:26:32</time>
|
25 |
+
<contents><target name="magecommunity"><dir name="Metrilo"><dir name="Analytics"><dir name="Block"><dir name="Adminhtml"><dir name="System"><dir name="Config"><dir name="Form"><file name="Button.php" hash="70aadb3d62d998a3076bd4f9209db560"/></dir></dir></dir></dir><file name="Head.php" hash="7fc6870506f8882520b4e2b9596600d7"/></dir><dir name="Helper"><file name="Data.php" hash="3b3d5f6796d7370863ce116107a90f1c"/></dir><dir name="Model"><file name="Import.php" hash="1eb20cd00c210ee378039edb8d0515dc"/><file name="Observer.php" hash="ca427229dd8f754efd4b3cf511c25cf6"/></dir><dir name="controllers"><dir name="Adminhtml"><file name="AjaxController.php" hash="0a16196c1c62b3359508b0b688a36e04"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="00c90fdba5e48bb35367c16c83abd6a7"/><file name="config.xml" hash="4708aed8284ec5c1457ca08a5ae079f6"/><file name="system.xml" hash="7564c68e51df23d7975bc1c9ead7be8f"/></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="metrilo_analytics.xml" hash="0e6911e2e883992f2182969286d929b1"/></dir><dir name="template"><dir name="metrilo"><dir name="system"><dir name="config"><file name="button.phtml" hash="528d7eb52bf996b7b2a31e8c6a4d7d86"/></dir></dir></dir></dir></dir></dir></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="metrilo"><file name="favicon-metrilo.png" hash="743558f1e49a730be9d515197a36567b"/><file name="loader.gif" hash="e05e6bb35d035cac4f3e0c8af213e9ab"/><file name="logo.png" hash="e9e54afd81384e12f77aca4eaebf5be8"/><file name="styles.css" hash="da0c07513d917e4ad08ff50814b536e1"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Metrilo_Analytics.xml" hash="3a4dbecc4e093537f11dd4c8fa2756e7"/></dir></target></contents>
|
26 |
+
<compatible/>
|
27 |
+
<dependencies><required><php><min>5.2.1</min><max>5.6.22</max></php></required></dependencies>
|
28 |
+
</package>
|
skin/adminhtml/default/default/metrilo/favicon-metrilo.png
ADDED
Binary file
|
skin/adminhtml/default/default/metrilo/loader.gif
ADDED
Binary file
|
skin/adminhtml/default/default/metrilo/logo.png
ADDED
Binary file
|
skin/adminhtml/default/default/metrilo/styles.css
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
ul.tabs a.metrilo-section span {
|
2 |
+
background: url(favicon-metrilo.png) no-repeat 18px 3px;
|
3 |
+
background-size: 23px;
|
4 |
+
overflow: hidden;
|
5 |
+
padding: 5px 0 5px 50px;
|
6 |
+
}
|
7 |
+
ul.tabs a.metrilo-section:hover span {
|
8 |
+
background: #D8E6E6 url(favicon-metrilo.png) no-repeat 18px 3px;
|
9 |
+
background-size: 23px;
|
10 |
+
padding: 5px 0 5px 50px;
|
11 |
+
}
|
12 |
+
#metrilo-info {
|
13 |
+
float:left;
|
14 |
+
width: calc(100% - 20px);
|
15 |
+
padding: 10px;
|
16 |
+
background-color: #fff;
|
17 |
+
border: 1px solid #ddd;
|
18 |
+
margin-bottom: 7px;
|
19 |
+
}
|
20 |
+
#metrilo-info img {
|
21 |
+
float:left;
|
22 |
+
width:50px;
|
23 |
+
}
|
24 |
+
#metrilo-info a {
|
25 |
+
color:#378FE2!important;
|
26 |
+
margin: 0;
|
27 |
+
}
|
28 |
+
#metrilo-info .text {
|
29 |
+
float:left;
|
30 |
+
margin-left: 10px;
|
31 |
+
padding-top: 5px;
|
32 |
+
}
|
33 |
+
#metrilo_import_status {
|
34 |
+
font-weight: bold;
|
35 |
+
vertical-align: middle;
|
36 |
+
display: flex;
|
37 |
+
padding: 10px 0;
|
38 |
+
}
|
39 |
+
#metrilo_import_status img {
|
40 |
+
margin-right: 5px;
|
41 |
+
}
|