Version Notes
Added feature to choose which events get pushed to Iterable.
Download this release
Release Info
Developer | Ilya Brin |
Extension | Iterable_Plugin |
Version | 1.1.0 |
Comparing to | |
See all releases |
Version 1.1.0
- app/code/community/Iterable/TrackOrderPlaced/Helper/Data.php +157 -0
- app/code/community/Iterable/TrackOrderPlaced/Model/Observer.php +349 -0
- app/code/community/Iterable/TrackOrderPlaced/Model/TrackingEventTypes.php +30 -0
- app/code/community/Iterable/TrackOrderPlaced/etc/config.xml +210 -0
- app/code/community/Iterable/TrackOrderPlaced/etc/system.xml +73 -0
- app/design/adminhtml/default/default/layout/iterable/common.xml +8 -0
- app/etc/modules/Iterable_TrackOrderPlaced.xml +26 -0
- package.xml +18 -0
- skin/adminhtml/base/default/iterable/images/section_logo.png +0 -0
- skin/adminhtml/base/default/iterable/iterable.css +5 -0
- skin/adminhtml/base/default/iterable/iterable.css~ +5 -0
app/code/community/Iterable/TrackOrderPlaced/Helper/Data.php
ADDED
@@ -0,0 +1,157 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Iterable_TrackOrderPlaced_Helper_Data extends Mage_Core_Helper_Abstract {
|
4 |
+
|
5 |
+
const XML_PATH_ITERABLE_API_KEY = 'api_options/api_key_options/api_key';
|
6 |
+
const XML_PATH_ENABLED_EVENTS = 'advanced_options/tracking_options/enabled_events';
|
7 |
+
|
8 |
+
private function getDecodedMagentoApiToken() {
|
9 |
+
$magentoApiKey = Mage::getStoreConfig(self::XML_PATH_ITERABLE_API_KEY);
|
10 |
+
return json_decode(base64_decode($magentoApiKey));
|
11 |
+
}
|
12 |
+
|
13 |
+
private function getIterableApiToken() {
|
14 |
+
$apiKeyJson = $this->getDecodedMagentoApiToken();
|
15 |
+
if ($apiKeyJson == NULL) {
|
16 |
+
return NULL;
|
17 |
+
}
|
18 |
+
return $apiKeyJson->t;
|
19 |
+
}
|
20 |
+
|
21 |
+
public function getNewsletterEmailListId() {
|
22 |
+
$apiKeyJson = $this->getDecodedMagentoApiToken();
|
23 |
+
if ($apiKeyJson == NULL) {
|
24 |
+
return NULL;
|
25 |
+
}
|
26 |
+
return $apiKeyJson->n;
|
27 |
+
}
|
28 |
+
|
29 |
+
public function getAccountEmailListId() {
|
30 |
+
$apiKeyJson = $this->getDecodedMagentoApiToken();
|
31 |
+
if ($apiKeyJson == NULL) {
|
32 |
+
return NULL;
|
33 |
+
}
|
34 |
+
return $apiKeyJson->u;
|
35 |
+
}
|
36 |
+
|
37 |
+
private function callIterableApi($event, $endpoint, $params) {
|
38 |
+
$eventsToTrack = Mage::getStoreConfig(self::XML_PATH_ENABLED_EVENTS);
|
39 |
+
$eventsToTrack = explode(",", $eventsToTrack);
|
40 |
+
if (!in_array($event, $eventsToTrack)) {
|
41 |
+
// TODO - maybe run this before gathering data about the cart
|
42 |
+
return;
|
43 |
+
}
|
44 |
+
$apiKey = $this->getIterableApiToken();
|
45 |
+
if ($apiKey == NULL) {
|
46 |
+
return;
|
47 |
+
}
|
48 |
+
$url = "https://api.iterable.com/{$endpoint}?api_key={$apiKey}";
|
49 |
+
try {
|
50 |
+
$client = new Zend_Http_Client($url);
|
51 |
+
} catch(Exception $e) {
|
52 |
+
Mage::log("Warning: unable to create http client with url {$url} ({$e->getMessage()})");
|
53 |
+
return;
|
54 |
+
}
|
55 |
+
$client->setMethod(Zend_Http_Client::POST);
|
56 |
+
// $client->setHeaders('Content-Type', 'application/json');
|
57 |
+
$json = json_encode($params);
|
58 |
+
$client->setRawData($json, 'application/json');
|
59 |
+
try {
|
60 |
+
$response = $client->request();
|
61 |
+
$status = $response->getStatus();
|
62 |
+
if ($status != 200) {
|
63 |
+
Mage::log("Iterable Tracker: Unable to track event at {$endpoint} with params {$json}; got status {$status} with body {$response->getBody()}");
|
64 |
+
}
|
65 |
+
} catch(Exception $e) {
|
66 |
+
Mage::log("Warning: unable to send event at {$endpoint} with params {$json} to Iterable ({$e->getMessage()})");
|
67 |
+
}
|
68 |
+
}
|
69 |
+
|
70 |
+
public function updateUser($email, $dataFields) {
|
71 |
+
$endpoint = '/api/users/update';
|
72 |
+
$params = array(
|
73 |
+
'email' => $email
|
74 |
+
);
|
75 |
+
if (!empty($dataFields)) {
|
76 |
+
$params['dataFields'] = $dataFields;
|
77 |
+
}
|
78 |
+
$this->callIterableApi(Iterable_TrackOrderPlaced_Model_TrackingEventTypes::EVENT_TYPE_USER, $endpoint, $params);
|
79 |
+
}
|
80 |
+
|
81 |
+
public function subscribeEmailToList($email, $listId, $dataFields=array(), $resubscribe=False) {
|
82 |
+
$endpoint = '/api/lists/subscribe';
|
83 |
+
$params = array(
|
84 |
+
'listId' => $listId,
|
85 |
+
'subscribers' => array(
|
86 |
+
array(
|
87 |
+
'email' => $email
|
88 |
+
)
|
89 |
+
),
|
90 |
+
'resubscribe' => $resubscribe
|
91 |
+
);
|
92 |
+
if (!empty($dataFields)) {
|
93 |
+
$params['subscribers'][0]['dataFields'] = $dataFields;
|
94 |
+
}
|
95 |
+
$this->callIterableApi(Iterable_TrackOrderPlaced_Model_TrackingEventTypes::EVENT_TYPE_NEWSLETTER_SUBSCRIBE, $endpoint, $params);
|
96 |
+
}
|
97 |
+
|
98 |
+
public function unsubscribeEmailFromList($email, $listId) {
|
99 |
+
$endpoint = '/api/lists/unsubscribe';
|
100 |
+
$params = array(
|
101 |
+
'listId' => $listId,
|
102 |
+
'subscribers' => array(
|
103 |
+
array(
|
104 |
+
'email' => $email
|
105 |
+
)
|
106 |
+
)
|
107 |
+
// 'campaignId' => iterableCid cookie?
|
108 |
+
);
|
109 |
+
$this->callIterableApi(Iterable_TrackOrderPlaced_Model_TrackingEventTypes::EVENT_TYPE_NEWSLETTER_UNSUBSCRIBE, $endpoint, $params);
|
110 |
+
}
|
111 |
+
|
112 |
+
/*
|
113 |
+
public function track($event, $email, $dataFields=array()) {
|
114 |
+
$endpoint = '/api/events/track';
|
115 |
+
$params = array(
|
116 |
+
'email' => $email,
|
117 |
+
'eventName' => $event
|
118 |
+
);
|
119 |
+
if (!empty($dataFields)) {
|
120 |
+
$params['dataFields'] = $dataFields;
|
121 |
+
}
|
122 |
+
$this->callIterableApi($event, $endpoint, $params);
|
123 |
+
}
|
124 |
+
*/
|
125 |
+
|
126 |
+
public function updateCart($email, $items, $dataFields=array()) {
|
127 |
+
$endpoint = '/api/commerce/updateCart';
|
128 |
+
$params = array(
|
129 |
+
'user' => array(
|
130 |
+
'email' => $email
|
131 |
+
),
|
132 |
+
'items' => $items
|
133 |
+
);
|
134 |
+
if (!empty($dataFields)) {
|
135 |
+
$params['user']['dataFields'] = $dataFields;
|
136 |
+
}
|
137 |
+
$this->callIterableApi(Iterable_TrackOrderPlaced_Model_TrackingEventTypes::EVENT_TYPE_CART_UPDATED, $endpoint, $params);
|
138 |
+
}
|
139 |
+
|
140 |
+
public function trackPurchase($email, $items, $campaignId=NULL, $dataFields=array()) {
|
141 |
+
$endpoint = '/api/commerce/trackPurchase';
|
142 |
+
$params = array(
|
143 |
+
'user' => array(
|
144 |
+
'email' => $email
|
145 |
+
),
|
146 |
+
'items' => $items
|
147 |
+
);
|
148 |
+
if (!empty($dataFields)) {
|
149 |
+
$params['user']['dataFields'] = $dataFields;
|
150 |
+
}
|
151 |
+
if ($campaignId != NULL) {
|
152 |
+
$params['campaignId'] = $campaignId;
|
153 |
+
}
|
154 |
+
$this->callIterableApi(Iterable_TrackOrderPlaced_Model_TrackingEventTypes::EVENT_TYPE_ORDER, $endpoint, $params);
|
155 |
+
}
|
156 |
+
|
157 |
+
}
|
app/code/community/Iterable/TrackOrderPlaced/Model/Observer.php
ADDED
@@ -0,0 +1,349 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Our class name should follow the directory structure of
|
4 |
+
* our Observer.php model, starting from the namespace,
|
5 |
+
* replacing directory separators with underscores.
|
6 |
+
* i.e. app/code/local/Iterable/
|
7 |
+
* TrackOrderPlaced/Model/Observer.php
|
8 |
+
*
|
9 |
+
* @author Iterable
|
10 |
+
*/
|
11 |
+
class Iterable_TrackOrderPlaced_Model_Observer
|
12 |
+
{
|
13 |
+
|
14 |
+
// HELPER FUNCTIONS
|
15 |
+
// TODO - move to Helpers
|
16 |
+
|
17 |
+
private function getCategories($product) {
|
18 |
+
// http://stackoverflow.com/questions/4252547/display-all-categories-that-a-product-belongs-to-in-magento
|
19 |
+
$currentCatIds = $product->getCategoryIds();
|
20 |
+
if (empty($currentCatIds)) {
|
21 |
+
return array();
|
22 |
+
}
|
23 |
+
$childCategories = Mage::getResourceModel('catalog/category_collection')
|
24 |
+
->addAttributeToSelect('name')
|
25 |
+
->addAttributeToSelect('url')
|
26 |
+
->addAttributeToFilter('entity_id', $currentCatIds)
|
27 |
+
->addIsActiveFilter();
|
28 |
+
$categories = array();
|
29 |
+
foreach($childCategories as $category) {
|
30 |
+
$curkey = &$categories;
|
31 |
+
$parents = $category->getParentCategories();
|
32 |
+
usort($parents,function($categoryA, $categoryB) { return $categoryA->getLevel() < $categoryB->getLevel() ? -1: 1; } );
|
33 |
+
/*
|
34 |
+
// if instead we want it in dictionary/map form, we can use this (also uasort instead of usort)
|
35 |
+
$lastName = end($parents)->getName();
|
36 |
+
foreach ($parents as $parentCat) {
|
37 |
+
$name = $parentCat->getName();
|
38 |
+
$isLast = $name == $lastName;
|
39 |
+
if (!array_key_exists($name, $curkey)) {
|
40 |
+
if ($isLast) {
|
41 |
+
array_push($curkey, $name);
|
42 |
+
} else {
|
43 |
+
$curkey[$name] = array();
|
44 |
+
}
|
45 |
+
}
|
46 |
+
if (!$isLast) { // assigning to that index creates it so don't assign
|
47 |
+
$curkey = &$curkey[$name];
|
48 |
+
}
|
49 |
+
}
|
50 |
+
*/
|
51 |
+
$names = array_map(function($c) { return $c->getName(); }, $parents);
|
52 |
+
array_push($categories, $names);
|
53 |
+
}
|
54 |
+
return $categories;
|
55 |
+
}
|
56 |
+
|
57 |
+
private function toIterableItem($product)
|
58 |
+
{
|
59 |
+
$item = $product;
|
60 |
+
$cls = get_class($product);
|
61 |
+
$isOrder = $cls == "Mage_Sales_Model_Order_Item";
|
62 |
+
$isQuote = $cls == "Mage_Sales_Model_Quote_Item";
|
63 |
+
if ($isOrder or $isQuote) {
|
64 |
+
$product = Mage::getModel('catalog/product')->load($item->getProductId());
|
65 |
+
}
|
66 |
+
$typeId = $product->getTypeId();
|
67 |
+
|
68 |
+
if ($isOrder) {
|
69 |
+
$price = $item->getPrice();
|
70 |
+
$quantity = $item->getQtyOrdered();
|
71 |
+
} elseif ($isQuote) {
|
72 |
+
$price = $item->getCalculationPrice();
|
73 |
+
$quantity = $item->getQty();
|
74 |
+
} else {
|
75 |
+
$price = ($typeId == Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) ?
|
76 |
+
// or maybe $pricemodel->getTotalBundleItemsPrice($product)
|
77 |
+
Mage::getModel('bundle/product_price')->getFinalPrice($qty=1.0, $product) :
|
78 |
+
$product->getPrice();
|
79 |
+
$quantity = intval($product->getCartQty());
|
80 |
+
}
|
81 |
+
|
82 |
+
$imageUrl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA).'catalog/product/'.$product->getImage();
|
83 |
+
$categoryNames = array();
|
84 |
+
foreach ($this->getCategories($product) as $categoryBreadcrumbs) {
|
85 |
+
$categoryNames[] = implode('/', $categoryBreadcrumbs);
|
86 |
+
}
|
87 |
+
return array(
|
88 |
+
'id' => $product->getEntityId(),
|
89 |
+
'sku' => $item->getSku(),
|
90 |
+
'name' => $item->getName(),
|
91 |
+
'categories' => $categoryNames,
|
92 |
+
//'itemDescription' => $product->getDescription(), // maybe use short description instead?
|
93 |
+
'imageUrl' => $imageUrl,
|
94 |
+
'url' => $product->getProductUrl(),
|
95 |
+
'quantity' => $quantity,
|
96 |
+
'price' => $price == NULL ? 0.0: floatval($price) // TODO - make sure price isn't NULL
|
97 |
+
//'dataFields' => array(
|
98 |
+
// 'typeId' => $typeId
|
99 |
+
//)
|
100 |
+
);
|
101 |
+
}
|
102 |
+
|
103 |
+
public function getItemsFromQuote($quote=NULL, $includeConfigurableSubproducts=TRUE)
|
104 |
+
{
|
105 |
+
if ($quote == NULL) {
|
106 |
+
$quote = Mage::getSingleton('checkout/session')->getQuote();
|
107 |
+
}
|
108 |
+
$quoteItems = array();
|
109 |
+
foreach ($quote->getAllItems() as $item) {
|
110 |
+
$iterableItem = $this->toIterableItem($item);
|
111 |
+
$parent = $item->getParentItem();
|
112 |
+
if (!$parent) {
|
113 |
+
$quoteItems[$item->getId()] = $iterableItem;
|
114 |
+
} /* else {
|
115 |
+
$parentItem = &$quoteItems[$parent->getId()];
|
116 |
+
if ($includeConfigurableSubproducts or ($parentItem['dataFields']['typeId'] != Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE)) {
|
117 |
+
if (!array_key_exists('subproducts', $parentItem)) {
|
118 |
+
$parentItem['subproducts'] = array();
|
119 |
+
}
|
120 |
+
array_push($parentItem['subproducts'], $iterableItem);
|
121 |
+
}
|
122 |
+
} */
|
123 |
+
}
|
124 |
+
return $quoteItems;
|
125 |
+
}
|
126 |
+
|
127 |
+
|
128 |
+
// EVENT HOOKS
|
129 |
+
|
130 |
+
private function sendCartUpdated($items=NULL)
|
131 |
+
{
|
132 |
+
if (!Mage::helper('customer')->isLoggedIn()) {
|
133 |
+
return;
|
134 |
+
}
|
135 |
+
if ($items == NULL) {
|
136 |
+
$items = array_values($this->getItemsFromQuote(NULL, FALSE));
|
137 |
+
}
|
138 |
+
$customer = Mage::getSingleton('customer/session')->getCustomer();
|
139 |
+
$helper = Mage::helper('trackorderplaced');
|
140 |
+
$helper->updateCart($customer->getEmail(), $items);
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Called when something is added to the cart
|
145 |
+
*/
|
146 |
+
public function checkoutCartProductAddAfter(Varien_Event_Observer $observer)
|
147 |
+
{
|
148 |
+
// it seems that the price is empty sometimes on a configurable, and this seems to fix that...
|
149 |
+
$quote = $observer->getEvent()->getQuoteItem()->getQuote();
|
150 |
+
$quote->collectTotals();
|
151 |
+
$quote->save();
|
152 |
+
|
153 |
+
$this->sendCartUpdated();
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* Called when a product is updated (quantity changed on item page, bundle reconfigured, etc)
|
158 |
+
*/
|
159 |
+
public function checkoutCartProductUpdateAfter(Varien_Event_Observer $observer)
|
160 |
+
{
|
161 |
+
$quote = $observer->getEvent()->getQuoteItem()->getQuote();
|
162 |
+
$quote->collectTotals();
|
163 |
+
$quote->save();
|
164 |
+
|
165 |
+
$this->sendCartUpdated();
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Called when quantities changed, etc on shopping cart page ("Update Shopping Cart" clicked)
|
170 |
+
*/
|
171 |
+
public function checkoutCartUpdateItemsAfter(Varien_Event_Observer $observer)
|
172 |
+
{
|
173 |
+
$this->sendCartUpdated();
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Called when something is removed from the cart (for example via the trash can symbol on cart page)
|
178 |
+
* Unforunately it also gets called on updateItems with quantity = 0, or when you reconfigure a configurable product with different options (so we'll get a few extra events)
|
179 |
+
*/
|
180 |
+
public function salesQuoteRemoveItem(Varien_Event_Observer $observer)
|
181 |
+
{
|
182 |
+
$this->sendCartUpdated();
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* Gets fired before the quote is saved. Seems to happen on changes to cart, in addition to whenever we view it
|
187 |
+
* There doesn't seem to be any event called when the user clicks "Clear Shopping Cart", so hook into this and check what they clicked
|
188 |
+
*/
|
189 |
+
public function salesQuoteSaveBefore(Varien_Event_Observer $observer)
|
190 |
+
{
|
191 |
+
$updateAction = (string)Mage::app()->getRequest()->getParam('update_cart_action');
|
192 |
+
|
193 |
+
if ($updateAction == 'empty_cart') {
|
194 |
+
$this->sendCartUpdated();
|
195 |
+
}
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
* Gets called when an order is placed
|
200 |
+
*/
|
201 |
+
public function orderPlaced(Varien_Event_Observer $observer)
|
202 |
+
{
|
203 |
+
$order = $observer->getEvent()->getOrder();
|
204 |
+
$orderItems = $this->getItemsFromQuote($order, FALSE);
|
205 |
+
$items = array_values($orderItems);
|
206 |
+
$email = $order->getCustomerEmail();
|
207 |
+
/*
|
208 |
+
$dataFields = array(
|
209 |
+
'firstName' => $order->getCustomerFirstname(),
|
210 |
+
'lastName' => $order->getCustomerLastname(),
|
211 |
+
'subtotal' => $order->getSubtotal(),
|
212 |
+
'grandTotal' => $order->getGrandTotal(),
|
213 |
+
'taxAmount' => $order->getTaxAmount(),
|
214 |
+
'shippingAmount' => $order->getShippingAmount(),
|
215 |
+
'items' => $items
|
216 |
+
);
|
217 |
+
*/
|
218 |
+
$cookieModel = Mage::getModel('core/cookie');
|
219 |
+
// $iterableUid = $cookieModel->get('iterable_uid');
|
220 |
+
$campaignId = $cookieModel->get('iterable_cid');
|
221 |
+
$campaignId = empty($campaignId) ? NULL: intval($campaignId);
|
222 |
+
// $dataFields["campaignId"] = $iterableCid;
|
223 |
+
$helper = Mage::helper('trackorderplaced');
|
224 |
+
$helper->trackPurchase($email, $items, $campaignId);
|
225 |
+
|
226 |
+
// don't need to clear cart, server does it automatically
|
227 |
+
}
|
228 |
+
|
229 |
+
/**
|
230 |
+
* Gets called when a customer saves their data
|
231 |
+
* Also seems to get called at several other times (after an order, etc)
|
232 |
+
*/
|
233 |
+
public function customerSaveAfter(Varien_Event_Observer $observer)
|
234 |
+
{
|
235 |
+
$customer = $observer->getCustomer();
|
236 |
+
|
237 |
+
$email = $customer->getEmail();
|
238 |
+
|
239 |
+
$dataFields = $customer->getData();
|
240 |
+
|
241 |
+
// set shipping address
|
242 |
+
$defaultShipping = $customer->getDefaultShippingAddress();
|
243 |
+
if ($defaultShipping) { $dataFields['defaultShipping'] = $defaultShipping->getData(); }
|
244 |
+
// set billing address
|
245 |
+
$defaultBilling = $customer->getDefaultBillingAddress();
|
246 |
+
if ($defaultBilling) { $dataFields['defaultBilling'] = $defaultBilling->getData(); }
|
247 |
+
// unset password/conf
|
248 |
+
$fieldsToUnset = array('password', 'password_hash', 'confirmation');
|
249 |
+
foreach ($fieldsToUnset as $fieldToUnset) {
|
250 |
+
if (array_key_exists($fieldToUnset, $dataFields)) {
|
251 |
+
unset($dataFields[$fieldToUnset]);
|
252 |
+
}
|
253 |
+
}
|
254 |
+
$helper = Mage::helper('trackorderplaced');
|
255 |
+
$helper->updateUser($email, $dataFields);
|
256 |
+
// if they're just creating their account, add them to a new users list
|
257 |
+
if (!$customer->getOrigData()) {
|
258 |
+
$listId = $helper->getAccountEmailListId();
|
259 |
+
if ($listId != NULL) {
|
260 |
+
$helper->subscribeEmailToList($email, $listId, $dataFields);
|
261 |
+
}
|
262 |
+
}
|
263 |
+
}
|
264 |
+
|
265 |
+
/*
|
266 |
+
public function addToCart(Varien_Event_Observer $observer)
|
267 |
+
{
|
268 |
+
Mage::log("add to cart!");
|
269 |
+
if (!Mage::helper('customer')->isLoggedIn()) {
|
270 |
+
return;
|
271 |
+
}
|
272 |
+
$customer = Mage::helper('customer')->getCustomer();
|
273 |
+
$email = $customer->getEmail();
|
274 |
+
$product = $observer->getProduct();
|
275 |
+
$cartItem = $this->toIterableItem($product);
|
276 |
+
$subproductsKey = 'subproducts';
|
277 |
+
$typeId = $product->getTypeId();
|
278 |
+
if ($typeId == Mage_Catalog_Model_Product_Type::TYPE_SIMPLE) {
|
279 |
+
// nothing extra to do for simple products
|
280 |
+
} elseif ($typeId == Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE) {
|
281 |
+
// configurable item seems to already have all important stuff set
|
282 |
+
} elseif ($typeId == Mage_Catalog_Model_Product_Type::TYPE_VIRTUAL) {
|
283 |
+
// hmm... probably nothing extra needed here
|
284 |
+
} elseif ($typeId == Mage_Catalog_Model_Product_Type::TYPE_GROUPED) {
|
285 |
+
$cartItem[$subproductsKey] = array();
|
286 |
+
$associatedProducts = $product->getTypeInstance(true)->getAssociatedProducts($product);
|
287 |
+
foreach ($associatedProducts as $associatedProduct) {
|
288 |
+
if (!$associatedProduct->getCartQty()) {
|
289 |
+
continue;
|
290 |
+
}
|
291 |
+
array_push($cartItem[$subproductsKey], $this->toIterableItem($associatedProduct));
|
292 |
+
}
|
293 |
+
} elseif ($typeId == Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) {
|
294 |
+
$cartItem[$subproductsKey] = array();
|
295 |
+
// also have thing in Mage_Bundle_Block_Catalog_Product_View_Type_Bundle
|
296 |
+
$bundlePriceHelper = Mage::getModel("bundle/product_price");
|
297 |
+
$optionsCollection = $bundlePriceHelper->getOptions($product);
|
298 |
+
foreach ($optionsCollection as $option) {
|
299 |
+
if (!$option->getSelections()) {
|
300 |
+
continue; // no selections
|
301 |
+
}
|
302 |
+
foreach ($option->getSelections() as $selection) {
|
303 |
+
// Mage::log("{$option->getTitle()} - {$selection->getName()} ({$selection->getCartQty()} @ {$selection->getPrice()})");
|
304 |
+
array_push($cartItem[$subproductsKey], $this->toIterableItem($selection));
|
305 |
+
}
|
306 |
+
}
|
307 |
+
} else {
|
308 |
+
// hmm...
|
309 |
+
}
|
310 |
+
|
311 |
+
$dataFields = array(
|
312 |
+
'item' => $cartItem
|
313 |
+
);
|
314 |
+
$helper = Mage::helper('trackorderplaced');
|
315 |
+
$helper->track(Iterable_TrackOrderPlaced_Model_TrackingEventTypes::EVENT_TYPE_ADD_TO_CART, $email, $dataFields);
|
316 |
+
}
|
317 |
+
*/
|
318 |
+
|
319 |
+
/**
|
320 |
+
* Called whenever a newsletter subscriber is saved
|
321 |
+
*/
|
322 |
+
public function newsletterSubscriberSaveAfter(Varien_Event_Observer $observer)
|
323 |
+
{
|
324 |
+
if (!$subscriber = $observer->getEvent()->getSubscriber()) {
|
325 |
+
return;
|
326 |
+
}
|
327 |
+
if (!$subscriber->getIsStatusChanged()) {
|
328 |
+
return; // don't send if nothing changed
|
329 |
+
}
|
330 |
+
$helper = Mage::helper('trackorderplaced');
|
331 |
+
$listId = $helper->getNewsletterEmailListId();
|
332 |
+
if ($listId == NULL) {
|
333 |
+
return;
|
334 |
+
}
|
335 |
+
$email = $subscriber->getSubscriberEmail();
|
336 |
+
$dataFields = $subscriber->getData();
|
337 |
+
switch ($subscriber->getStatus()) {
|
338 |
+
case Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED:
|
339 |
+
$helper->subscribeEmailToList($email, $listId, $dataFields, True);
|
340 |
+
break;
|
341 |
+
case Mage_Newsletter_Model_Subscriber::STATUS_UNSUBSCRIBED:
|
342 |
+
$helper->unsubscribeEmailFromList($email, $listId);
|
343 |
+
break;
|
344 |
+
default:
|
345 |
+
break;
|
346 |
+
}
|
347 |
+
}
|
348 |
+
|
349 |
+
}
|
app/code/community/Iterable/TrackOrderPlaced/Model/TrackingEventTypes.php
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Iterable_TrackOrderPlaced_Model_TrackingEventTypes
|
4 |
+
{
|
5 |
+
|
6 |
+
const EVENT_TYPE_ORDER = 'order';
|
7 |
+
const EVENT_TYPE_USER = 'user';
|
8 |
+
const EVENT_TYPE_CART_UPDATED = 'cartUpdated';
|
9 |
+
const EVENT_TYPE_NEWSLETTER_SUBSCRIBE = 'newsletterSubscribe';
|
10 |
+
const EVENT_TYPE_NEWSLETTER_UNSUBSCRIBE = 'newsletterUnsubscribe';
|
11 |
+
|
12 |
+
/** @const */
|
13 |
+
private static $eventTypes = array(
|
14 |
+
self::EVENT_TYPE_ORDER => 'Orders',
|
15 |
+
self::EVENT_TYPE_USER => 'User',
|
16 |
+
self::EVENT_TYPE_CART_UPDATED => 'Cart Updated',
|
17 |
+
self::EVENT_TYPE_NEWSLETTER_SUBSCRIBE => 'Newsletter Subscribe',
|
18 |
+
self::EVENT_TYPE_NEWSLETTER_UNSUBSCRIBE => 'Newsletter Unsubscribe'
|
19 |
+
);
|
20 |
+
|
21 |
+
public function toOptionArray()
|
22 |
+
{
|
23 |
+
$events = array();
|
24 |
+
foreach (self::$eventTypes as $key => $name) {
|
25 |
+
$events[] = array('value' => $key, 'label'=>Mage::helper('trackorderplaced')->__($name));
|
26 |
+
}
|
27 |
+
return $events;
|
28 |
+
}
|
29 |
+
|
30 |
+
}
|
app/code/community/Iterable/TrackOrderPlaced/etc/config.xml
ADDED
@@ -0,0 +1,210 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<!--
|
3 |
+
/**
|
4 |
+
* Module configuration
|
5 |
+
*
|
6 |
+
* @author Iterable
|
7 |
+
*/
|
8 |
+
-->
|
9 |
+
<!-- The root node for Magento module configuration -->
|
10 |
+
<config>
|
11 |
+
|
12 |
+
<!--
|
13 |
+
The module's node contains basic
|
14 |
+
information about each Magento module
|
15 |
+
-->
|
16 |
+
<modules>
|
17 |
+
<!--
|
18 |
+
This must exactly match the namespace and module's folder
|
19 |
+
names, with directory separators replaced by underscores
|
20 |
+
-->
|
21 |
+
<Iterable_TrackOrderPlaced>
|
22 |
+
<!-- The version of our module, starting at 0.0.1 -->
|
23 |
+
<version>0.0.1</version>
|
24 |
+
</Iterable_TrackOrderPlaced>
|
25 |
+
</modules>
|
26 |
+
|
27 |
+
<!-- Configure our module's behavior in the global scope -->
|
28 |
+
<global>
|
29 |
+
|
30 |
+
<helpers>
|
31 |
+
<trackorderplaced>
|
32 |
+
<class>Iterable_TrackOrderPlaced_Helper</class>
|
33 |
+
</trackorderplaced>
|
34 |
+
</helpers>
|
35 |
+
|
36 |
+
<models>
|
37 |
+
<iterable_trackorderplaced>
|
38 |
+
<class>Iterable_TrackOrderPlaced_Model</class>
|
39 |
+
</iterable_trackorderplaced>
|
40 |
+
</models>
|
41 |
+
|
42 |
+
<!-- Defining an event observer -->
|
43 |
+
<events>
|
44 |
+
<!-- The code of the event we want to observe -->
|
45 |
+
<sales_order_place_after>
|
46 |
+
<!-- Defining an observer for this event -->
|
47 |
+
<observers>
|
48 |
+
<!--
|
49 |
+
Unique identifier within the
|
50 |
+
catalog_product_save_after node.
|
51 |
+
By convention, we write the module's
|
52 |
+
name in lowercase.
|
53 |
+
-->
|
54 |
+
<iterable_trackorderplaced>
|
55 |
+
<!-- The model to be instantiated -->
|
56 |
+
<class>iterable_trackorderplaced/observer</class>
|
57 |
+
<!-- The method of the class to be called -->
|
58 |
+
<method>orderPlaced</method>
|
59 |
+
<!-- The type of class to instantiate -->
|
60 |
+
<type>singleton</type>
|
61 |
+
</iterable_trackorderplaced>
|
62 |
+
</observers>
|
63 |
+
</sales_order_place_after>
|
64 |
+
<customer_save_after>
|
65 |
+
<observers>
|
66 |
+
<iterable_trackaccountcreated>
|
67 |
+
<class>iterable_trackorderplaced/observer</class>
|
68 |
+
<method>customerSaveAfter</method>
|
69 |
+
<type>singleton</type>
|
70 |
+
</iterable_trackaccountcreated>
|
71 |
+
</observers>
|
72 |
+
</customer_save_after>
|
73 |
+
<!--
|
74 |
+
<customer_address_save_after>
|
75 |
+
<observers>
|
76 |
+
<iterable_trackaccountcreated>
|
77 |
+
<class>iterable_trackorderplaced/observer</class>
|
78 |
+
<method>customerSaveAfter</method>
|
79 |
+
<type>singleton</type>
|
80 |
+
</iterable_trackaccountcreated>
|
81 |
+
</observers>
|
82 |
+
</customer_address_save_after>
|
83 |
+
-->
|
84 |
+
<!-- tracks additions to the cart, but doesn't track changed quantities -->
|
85 |
+
<!--
|
86 |
+
<checkout_cart_add_product_complete>
|
87 |
+
<observers>
|
88 |
+
<iterable_trackaddtocart>
|
89 |
+
<class>iterable_trackorderplaced/observer</class>
|
90 |
+
<method>addToCart</method>
|
91 |
+
<type>singleton</type>
|
92 |
+
</iterable_trackaddtocart>
|
93 |
+
</observers>
|
94 |
+
</checkout_cart_add_product_complete>
|
95 |
+
checkout_cart_update_item_complete
|
96 |
+
-->
|
97 |
+
<checkout_cart_product_add_after>
|
98 |
+
<observers>
|
99 |
+
<iterable_trackaddtocart>
|
100 |
+
<class>iterable_trackorderplaced/observer</class>
|
101 |
+
<method>checkoutCartProductAddAfter</method>
|
102 |
+
<type>singleton</type>
|
103 |
+
</iterable_trackaddtocart>
|
104 |
+
</observers>
|
105 |
+
</checkout_cart_product_add_after>
|
106 |
+
<checkout_cart_product_update_after>
|
107 |
+
<observers>
|
108 |
+
<iterable_trackupdatecart>
|
109 |
+
<class>iterable_trackorderplaced/observer</class>
|
110 |
+
<method>checkoutCartProductUpdateAfter</method>
|
111 |
+
<type>singleton</type>
|
112 |
+
</iterable_trackupdatecart>
|
113 |
+
</observers>
|
114 |
+
</checkout_cart_product_update_after>
|
115 |
+
<checkout_cart_update_items_after>
|
116 |
+
<observers>
|
117 |
+
<iterable_trackupdatecart>
|
118 |
+
<class>iterable_trackorderplaced/observer</class>
|
119 |
+
<method>checkoutCartUpdateItemsAfter</method>
|
120 |
+
<type>singleton</type>
|
121 |
+
</iterable_trackupdatecart>
|
122 |
+
</observers>
|
123 |
+
</checkout_cart_update_items_after>
|
124 |
+
<!-- should use cart events instead of quote events, quote events don't get fired when quantity changes... however we still need the remove
|
125 |
+
<sales_quote_add_item>
|
126 |
+
<observers>
|
127 |
+
<iterable_trackupdatecart>
|
128 |
+
<class>iterable_trackorderplaced/observer</class>
|
129 |
+
<method>salesQuoteAddItem</method>
|
130 |
+
<type>singleton</type>
|
131 |
+
</iterable_trackupdatecart>
|
132 |
+
</observers>
|
133 |
+
</sales_quote_add_item>
|
134 |
+
-->
|
135 |
+
<sales_quote_save_before>
|
136 |
+
<observers>
|
137 |
+
<iterable_trackclearcart>
|
138 |
+
<class>iterable_trackorderplaced/observer</class>
|
139 |
+
<method>salesQuoteSaveBefore</method>
|
140 |
+
<type>singleton</type>
|
141 |
+
</iterable_trackclearcart>
|
142 |
+
</observers>
|
143 |
+
</sales_quote_save_before>
|
144 |
+
<sales_quote_remove_item>
|
145 |
+
<observers>
|
146 |
+
<iterable_trackupdatecart>
|
147 |
+
<class>iterable_trackorderplaced/observer</class>
|
148 |
+
<method>salesQuoteRemoveItem</method>
|
149 |
+
<type>singleton</type>
|
150 |
+
</iterable_trackupdatecart>
|
151 |
+
</observers>
|
152 |
+
</sales_quote_remove_item>
|
153 |
+
<newsletter_subscriber_save_after>
|
154 |
+
<observers>
|
155 |
+
<iterable_tracknewslettersubscribe>
|
156 |
+
<class>iterable_trackorderplaced/observer</class>
|
157 |
+
<method>newsletterSubscriberSaveAfter</method>
|
158 |
+
<type>singleton</type>
|
159 |
+
</iterable_tracknewslettersubscribe>
|
160 |
+
</observers>
|
161 |
+
</newsletter_subscriber_save_after>
|
162 |
+
</events>
|
163 |
+
</global>
|
164 |
+
|
165 |
+
<default>
|
166 |
+
<api_options>
|
167 |
+
<api_key_options>
|
168 |
+
<api_key>MAGENTO_API_KEY</api_key>
|
169 |
+
</api_key_options>
|
170 |
+
</api_options>
|
171 |
+
<advanced_options>
|
172 |
+
<tracking_options>
|
173 |
+
<enabled_events>order,user,cartUpdated,newsletterSubscribe,newsletterUnsubscribe</enabled_events>
|
174 |
+
</tracking_options>
|
175 |
+
</advanced_options>
|
176 |
+
</default>
|
177 |
+
|
178 |
+
<adminhtml>
|
179 |
+
<layout>
|
180 |
+
<updates>
|
181 |
+
<iterable_trackorderplaced>
|
182 |
+
<file>iterable/common.xml</file>
|
183 |
+
</iterable_trackorderplaced>
|
184 |
+
</updates>
|
185 |
+
</layout>
|
186 |
+
<acl>
|
187 |
+
<resources>
|
188 |
+
<admin>
|
189 |
+
<children>
|
190 |
+
<system>
|
191 |
+
<children>
|
192 |
+
<config>
|
193 |
+
<children>
|
194 |
+
<api_options>
|
195 |
+
<title>Iterable API Module</title>
|
196 |
+
</api_options>
|
197 |
+
<advanced_options>
|
198 |
+
<title>Iterable Advanced Module</title>
|
199 |
+
</advanced_options>
|
200 |
+
</children>
|
201 |
+
</config>
|
202 |
+
</children>
|
203 |
+
</system>
|
204 |
+
</children>
|
205 |
+
</admin>
|
206 |
+
</resources>
|
207 |
+
</acl>
|
208 |
+
</adminhtml>
|
209 |
+
|
210 |
+
</config>
|
app/code/community/Iterable/TrackOrderPlaced/etc/system.xml
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<config>
|
2 |
+
<tabs> <!-- heading in the left-side navigation -->
|
3 |
+
<iterableconfig translate="label" module="trackorderplaced">
|
4 |
+
<label><![CDATA[<div>Iterable</div>]]></label>
|
5 |
+
<class>iterable-section</class>
|
6 |
+
<sort_order>101</sort_order> <!-- General is 100, from app/code/core/Mage/Core/etc/system.xml -->
|
7 |
+
</iterableconfig>
|
8 |
+
</tabs>
|
9 |
+
<sections> <!-- each section defined here is a subcategory of a heading from tabs. EACH SECTION NEEDS AN ACL DEFINED IN CONFIG.XML -->
|
10 |
+
<api_options translate="label" module="trackorderplaced">
|
11 |
+
<label>API</label>
|
12 |
+
<tab>iterableconfig</tab>
|
13 |
+
<frontend_type>text</frontend_type>
|
14 |
+
<sort_order>1000</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 |
+
<groups>
|
19 |
+
<api_key_options translate="label">
|
20 |
+
<label>API Key</label>
|
21 |
+
<frontend_type>text</frontend_type>
|
22 |
+
<expanded>1</expanded>
|
23 |
+
<sort_order>1</sort_order>
|
24 |
+
<show_in_default>1</show_in_default>
|
25 |
+
<show_in_website>1</show_in_website>
|
26 |
+
<show_in_store>1</show_in_store>
|
27 |
+
<fields>
|
28 |
+
<api_key>
|
29 |
+
<label>API Key</label>
|
30 |
+
<comment>Your unique API key. Can be found in your Iterable account <![CDATA[<a href="https://iterable.com/api/settings">here</a>]]>.</comment>
|
31 |
+
<frontend_type>text</frontend_type>
|
32 |
+
<sort_order>1</sort_order>
|
33 |
+
<show_in_default>1</show_in_default>
|
34 |
+
<show_in_website>1</show_in_website>
|
35 |
+
<show_in_store>1</show_in_store>
|
36 |
+
</api_key>
|
37 |
+
</fields>
|
38 |
+
</api_key_options>
|
39 |
+
</groups>
|
40 |
+
</api_options>
|
41 |
+
<advanced_options>
|
42 |
+
<label>Advanced</label>
|
43 |
+
<tab>iterableconfig</tab>
|
44 |
+
<frontend_type>text</frontend_type>
|
45 |
+
<sort_order>1001</sort_order>
|
46 |
+
<show_in_default>1</show_in_default>
|
47 |
+
<show_in_website>1</show_in_website>
|
48 |
+
<show_in_store>1</show_in_store>
|
49 |
+
<groups>
|
50 |
+
<tracking_options translate="label">
|
51 |
+
<label>Event Tracking</label>
|
52 |
+
<frontend_type>text</frontend_type>
|
53 |
+
<sort_order>2</sort_order>
|
54 |
+
<show_in_default>1</show_in_default>
|
55 |
+
<show_in_website>1</show_in_website>
|
56 |
+
<show_in_store>1</show_in_store>
|
57 |
+
<fields>
|
58 |
+
<enabled_events>
|
59 |
+
<label>Events</label>
|
60 |
+
<comment>The types of events to push to Iterable</comment>
|
61 |
+
<frontend_type>multiselect</frontend_type>
|
62 |
+
<source_model>iterable_trackorderplaced/trackingeventtypes</source_model>
|
63 |
+
<sort_order>1</sort_order>
|
64 |
+
<show_in_default>1</show_in_default>
|
65 |
+
<show_in_website>1</show_in_website>
|
66 |
+
<show_in_store>1</show_in_store>
|
67 |
+
</enabled_events>
|
68 |
+
</fields>
|
69 |
+
</tracking_options>
|
70 |
+
</groups>
|
71 |
+
</advanced_options>
|
72 |
+
</sections>
|
73 |
+
</config>
|
app/design/adminhtml/default/default/layout/iterable/common.xml
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<layout>
|
3 |
+
<adminhtml_system_config_edit>
|
4 |
+
<reference name="head">
|
5 |
+
<action method="addCss"><stylesheet>iterable/iterable.css</stylesheet></action>
|
6 |
+
</reference>
|
7 |
+
</adminhtml_system_config_edit>
|
8 |
+
</layout>
|
app/etc/modules/Iterable_TrackOrderPlaced.xml
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<!--
|
3 |
+
/**
|
4 |
+
* Module initial config
|
5 |
+
*
|
6 |
+
* @author Iterable
|
7 |
+
*/
|
8 |
+
-->
|
9 |
+
<config>
|
10 |
+
<modules>
|
11 |
+
<Iterable_TrackOrderPlaced>
|
12 |
+
|
13 |
+
<!-- Whether our module is active: true or false -->
|
14 |
+
<active>true</active>
|
15 |
+
|
16 |
+
<!-- Which code pool to use: core, community or local -->
|
17 |
+
<codePool>community</codePool>
|
18 |
+
|
19 |
+
<!-- Which modules our code depends on -->
|
20 |
+
<depends>
|
21 |
+
<!-- <Iterable_Tracker/> -->
|
22 |
+
</depends>
|
23 |
+
|
24 |
+
</Iterable_TrackOrderPlaced>
|
25 |
+
</modules>
|
26 |
+
</config>
|
package.xml
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<package>
|
3 |
+
<name>Iterable_Plugin</name>
|
4 |
+
<version>1.1.0</version>
|
5 |
+
<stability>stable</stability>
|
6 |
+
<license uri="http://opensource.org/licenses/OSL-3.0">Open Software License (OSL) </license>
|
7 |
+
<channel>community</channel>
|
8 |
+
<extends/>
|
9 |
+
<summary>Automatically tie together your commerce platform and email marketing with this plugin from Iterable!</summary>
|
10 |
+
<description>After installing this plugin, you will be able to immediately view and take action in the Iterable platform whenever your Magento users make important decisions, such as signing up or making a purchase! Easily integrate and set up abandoned cart emails, handle newsletter subscriptions, or reach out to customers whenever they make a purchase. </description>
|
11 |
+
<notes>Added feature to choose which events get pushed to Iterable.</notes>
|
12 |
+
<authors><author><name>Ilya Brin</name><user>Iterable</user><email>ilya@iterable.com</email></author></authors>
|
13 |
+
<date>2014-04-30</date>
|
14 |
+
<time>03:23:26</time>
|
15 |
+
<contents><target name="magecommunity"><dir name="Iterable"><dir name="TrackOrderPlaced"><dir name="Helper"><file name="Data.php" hash="661ec5234fee78ffeae3d77011a2dde1"/></dir><dir name="Model"><file name="Observer.php" hash="d110ed71f94f2bff983e88ca1551ae2d"/><file name="TrackingEventTypes.php" hash="f0592c7a7506a0e606275dd422a57bb8"/></dir><dir name="etc"><file name="config.xml" hash="d9e0eae78379f3c6238d70023b110276"/><file name="system.xml" hash="e4ad1b58022f8969e64dff80971c4cfb"/></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><dir name="iterable"><file name="common.xml" hash="d90fbb22fb34fa29deb6b0e131f9e767"/></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Iterable_TrackOrderPlaced.xml" hash="0d4506dadf95eecb54e215ed03b2c6a7"/></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="base"><dir name="default"><dir name="iterable"><dir name="images"><file name="section_logo.png" hash="fe5090ba955a890c1efe2c09cb260342"/></dir><file name="iterable.css" hash="4d928c5a4ed76d62e246a57ee868ec23"/><file name="iterable.css~" hash="2c3ee0498f159bc59bee37cd3c508f27"/></dir></dir></dir></dir></target></contents>
|
16 |
+
<compatible/>
|
17 |
+
<dependencies><required><php><min>5.4.1</min><max>6.0.0</max></php></required></dependencies>
|
18 |
+
</package>
|
skin/adminhtml/base/default/iterable/images/section_logo.png
ADDED
Binary file
|
skin/adminhtml/base/default/iterable/iterable.css
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.iterable-section > dl > dt.label > div {
|
2 |
+
height: 22px;
|
3 |
+
text-indent: -9999px;
|
4 |
+
background: url(images/section_logo.png) no-repeat -1px -1px;
|
5 |
+
}
|
skin/adminhtml/base/default/iterable/iterable.css~
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.bronto-section > dl > dt.label > div {
|
2 |
+
height: 22px;
|
3 |
+
text-indent: -9999px;
|
4 |
+
background: url(images/section_logo.png) no-repeat -1px -1px;
|
5 |
+
}
|