pixlee-for-magento - Version 2.0.0.1

Version Notes

This plugin is an upgrade to the Pixlee Magento plugin 1.0.0. It includes the following improvements -

1. Product exports updated to use Pixlee V2 API
- Product exports now send inventory (stock) information
- Product exports on "configurable" and "grouped" products now also send a JSON of IDs/SKUs of associated products

2. Standardized Analytics
Add to Cart and Remove From Cart analytics will now include the following fields
- product_id
- product_sku
- variant_id
- variant_sku
- quantity
- price

Checkout Start and Conversion will now include the following fields
- cart_contents (Summary of all the products in the cart)
- cart_total (net price)
- cart_total_quantity
- currency
- order_id

In addition to those fields, all of the events will include the following fields
- ecommerce_platform (magento_1)
- ecommerce_version (version of the plugin)
- version_hash - refers to the latest git commit hash in the master branch

3. Recognizing unique users
All of the users are now tracked using a 'distinct_user_hash' which is issued by Segment. To keep the 'distinct_user_hash' consistent throughout the period of time when the user is on the website - we use segment to only issue a distinct_user_hash relative to photos.pixlee.com. This helps us to recognize all users even if they we re-directed to a different domain.

Download this release

Release Info

Developer Awad Sayeed
Extension pixlee-for-magento
Version 2.0.0.1
Comparing to
See all releases


Code changes from version 2.0.0 to 2.0.0.1

app/design/adminhtml/default/default/layout/pixlee/base.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>pixlee/base.css</stylesheet></action>
6
+ </reference>
7
+ </adminhtml_system_config_edit>
8
+ </layout>
app/design/adminhtml/default/default/template/pixlee/system/config/export_button.phtml ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script type="text/javascript">
2
+ //<![CDATA[
3
+ function exportToPixlee(url) {
4
+ if($('pixlee_export_button').hasClassName('disabled')) {
5
+ return;
6
+ }
7
+ $('pixlee_export_button').addClassName('disabled');
8
+ new Ajax.Request(url, {
9
+ method: 'get',
10
+ onSuccess: function(transport){
11
+ if (transport.responseText){
12
+ var json = transport.responseText.evalJSON(true);
13
+ if(json.pixlee_remaining_text) {
14
+ $('pixlee_remaining').update(json.pixlee_remaining_text);
15
+ }
16
+ if(json.action == 'continue' && json.url) {
17
+ $('pixlee_export_button').removeClassName('disabled');
18
+ exportToPixlee(json.url);
19
+ }
20
+ }
21
+ }
22
+ });
23
+ }
24
+ //]]>
25
+ </script>
26
+
27
+ <?php echo $this->getButtonHtml() ?>
28
+ <p class="note"><span id="pixlee_remaining"><?php echo Mage::helper('pixlee')->getPixleeRemainingText(); ?></span></p>
app/design/frontend/base/default/layout/pixlee/gallery.xml ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <layout version="0.1.0">
3
+ <!--
4
+ To implement the Pixlee gallery, insert the "pixlee_gallery_tag"
5
+ update handle in the layout XML for your page. Example:
6
+
7
+ <catalog_product_view translate="label">
8
+ <update handle="pixlee_gallery_tag" />
9
+ </catalog_product_view>
10
+
11
+ Once you've added the update handle, the Pixlee external JS script
12
+ will be embedded in the head of the page and you should be able to
13
+ make the following call anywhere on that page:
14
+
15
+ <?php echo $this->getLayout()->createBlock('pixlee/gallery')->toHtml(); ?>
16
+
17
+ The above will embed the Pixlee gallery in place and handle any
18
+ responsive design you can throw at it.
19
+
20
+ The Pixlee extension will attempt to discern the current product's
21
+ SKU automatically in order to display the correct gallery, but if
22
+ it is unable to do so you can explicitly set the product SKU with
23
+ the "setProductSku" function like so:
24
+
25
+ <?php echo $this->getLayout()->createBlock('pixlee/gallery')->setProductSku($SKU)->toHtml(); ?>
26
+ -->
27
+ <pixlee_gallery_tag translate="label">
28
+ <label>Pixlee gallery and external script</label>
29
+
30
+ <reference name="head">
31
+ <!-- <block type="core/text" name="pixlee_external_js" as="pixlee_external_js">
32
+ <action method="setText"><text><![CDATA[<script src="//assets.pixlee.com/javascripts/embed/widget/pixlee_widget.v2.js"></script>]]></text></action>
33
+ </block> -->
34
+ </reference>
35
+
36
+ </pixlee_gallery_tag>
37
+
38
+ <default translate="label">
39
+ <update handle="pixlee_gallery_tag" />
40
+ </default>
41
+
42
+ </layout>
app/design/frontend/base/default/template/pixlee/gallery.phtml ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $helper = Mage::helper('pixlee');
3
+ $productSku = $this->getProductSku();
4
+ if($helper->isActive() && !empty($productSku)):
5
+ $pixleeAccountId = $this->getAccountId();
6
+ $pixleeRecipeId = $this->getRecipeId();
7
+ $pixleeDisplayOptionsId = $this->getDisplayOptionsId();
8
+ $pixleeAccountApiKey = $this->getAccountApiKey();
9
+ ?>
10
+ <div id="pixlee_container"></div>
11
+ <div id="pixlee_widget_master_container"></div>
12
+ <script id="pixlee_script">
13
+
14
+ window.PixleeAsyncInit = function() {
15
+ Pixlee.init({
16
+ apiKey: '<?php echo $pixleeAccountApiKey; ?>'
17
+ });
18
+ Pixlee.addProductWidget({
19
+ skuId: '<?php echo $productSku; ?>',
20
+ recipeId: <?php echo $pixleeRecipeId; ?>,
21
+ displayOptionsId: <?php echo $pixleeDisplayOptionsId; ?>,
22
+ type:"horizontal",
23
+ accountId:<?php echo $pixleeAccountId; ?>
24
+ });
25
+ };
26
+ </script>
27
+ <script src="https://assets.pixlee.com/assets/pixlee_widget_1_0_0.js"></script>
28
+
29
+ <?php elseif(empty($productSku)): ?>
30
+ <!-- Could not display the Pixlee gallery. No product SKU found. Try explicitly setting one with the "setProductSku" function after creating the block. -->
31
+ <?php else: ?>
32
+ <!-- Could not display the Pixlee gallery. Make sure all the required credentials are saved in the Magento admin panel! -->
33
+ <?php endif; ?>
app/etc/modules/Pixlee_Base.xml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Pixlee_Base>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ <depends></depends>
8
+ </Pixlee_Base>
9
+ </modules>
10
+ </config>
lib/Pixlee/Pixlee.php ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Pixlee_Pixlee {
3
+ private $apiKey;
4
+ private $baseURL;
5
+
6
+ // Constructor - distillery no longer REQUIRES secretKey or userID
7
+ // Also, make explicit the fact that we're no longer passing the user key,
8
+ // but the account key
9
+ public function __construct($accountApiKey){
10
+ if( is_null( $accountApiKey )){
11
+ throw new Exception("An API Key is required");
12
+ }
13
+ $this->apiKey = $accountApiKey;
14
+ $this->baseURL = "http://distillery.pixlee.com/api/v2";
15
+ }
16
+
17
+ public function getAlbums(){
18
+ return $this->getFromAPI("/albums");
19
+ }
20
+
21
+ // The following functions don't seem to be used anywhere
22
+ // The only functions I seem to NEED are:
23
+ // 1) getAlbums, to make sure that the config is right, and we can hit the API
24
+ // 2) createProduct, which doubles as "updateProduct," via POST
25
+ // Not going to spend time figuring out the distillery versions of the following
26
+ // v1 API calls, but leaving the original declarations here, in case I'm wrong
27
+ /*
28
+ public function getPhotos($albumID, $options = NULL ){
29
+ return $this->getFromAPI( "/albums/$albumID/photos", $options);
30
+ }
31
+ public function getPhoto($albumID, $photoID, $options = NULL ){
32
+ return $this->getFromAPI( "/albums/$albumID/photos/$photoID", $options);
33
+ }
34
+ // ex of $media = array('photo_url' => $newPhotoURL, 'email_address' => $email_address, 'type' => $type);
35
+ public function createPhoto($albumID, $media){
36
+ // assign media to the data key
37
+ $data = array('media' => $media);
38
+ $payload = $this->signedData($data);
39
+ return $this->postToAPI( "/albums/$albumID/photos", $payload );
40
+ }
41
+ */
42
+
43
+ public function createProduct($product_name, $sku, $product_url , $product_image, $product_id = NULL, $aggregateStock = NULL, $variantsDict = NULL){
44
+ Mage::log("* In createProduct");
45
+ /*
46
+ Converted from Rails API format to distillery API format
47
+ Also, now sending _account_ 'api_key' instead of _user_ 'api_key'
48
+ Instead of:
49
+ {
50
+ 'album': {
51
+ 'album_name': <VAL>
52
+ }
53
+ 'product: {
54
+ 'name': <VAL>,
55
+ 'sku': <VAL>,
56
+ 'buy_now_link_url': <VAL>,
57
+ 'product_photo': <VAL>
58
+ }
59
+ }
60
+ Is now:
61
+ {
62
+ 'title': <VAL>,
63
+ 'album_type': <VAL>,
64
+ 'num_photo': <VAL>,
65
+ 'num_inbox_photo': <VAL>,
66
+ 'product':
67
+ 'name': <VAL>,
68
+ 'sku': <VAL>,
69
+ 'buy_now_link_url': <VAL>,
70
+ 'product_photo': <VAL>
71
+ }
72
+ }
73
+ */
74
+ $product = array('name' => $product_name, 'sku' => $sku, 'buy_now_link_url' => $product_url,
75
+ 'product_photo' => $product_image, 'stock' => $aggregateStock,
76
+ 'native_product_id' => $product_id, 'variants_json' => $variantsDict);
77
+ $data = array('title' => $product_name, 'album_type' => 'product', 'num_photo' => 0,
78
+ 'num_inbox_photo' => 0, 'product' => $product);
79
+ $payload = $this->signedData($data);
80
+ return $this->postToAPI( "/albums?api_key=" . $this->apiKey, $payload );
81
+ }
82
+
83
+ // Private functions
84
+ private function getFromAPI( $uri, $options = NULL ){
85
+ $apiString = "?api_key=".$this->apiKey;
86
+ $urlToHit = $this->baseURL;
87
+ $urlToHit = $urlToHit . $uri . $apiString;
88
+
89
+ if( !is_null($options)){
90
+ $queryString = http_build_query($options);
91
+ $urlToHit = $urlToHit . "&" . $queryString;
92
+ }
93
+
94
+ $ch = curl_init( $urlToHit );
95
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
96
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
97
+ curl_setopt($ch, CURLOPT_HTTPHEADER, array(
98
+ 'Content-Type: application/json'
99
+ )
100
+ );
101
+ $response = curl_exec($ch);
102
+
103
+ return $this->handleResponse($response, $ch);
104
+ }
105
+
106
+ private function postToAPI($uri, $payload){
107
+ Mage::log("*** In postToAPI");
108
+ Mage::log("With this URI: {$uri}");
109
+ $urlToHit = $this->baseURL . $uri;
110
+
111
+ $ch = curl_init( $urlToHit );
112
+ Mage::log("Hitting URL: {$urlToHit}");
113
+ Mage::log("With payload: {$payload}");
114
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
115
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
116
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
117
+ curl_setopt($ch, CURLOPT_HTTPHEADER, array(
118
+ 'Content-Type: application/json',
119
+ 'Content-Length: ' . strlen($payload)
120
+ )
121
+ );
122
+ $response = curl_exec($ch);
123
+
124
+ Mage::log("Got response: {$response}");
125
+ return $this->handleResponse($response, $ch);
126
+ }
127
+
128
+ // The rails API takes a signature, which was a sha256 of the payload
129
+ // we were about to send, JSONified.
130
+ // There was also a check for a JSON_UNESCAPED_SLASHES constant, which would
131
+ // 'fix' the JSON before encoding, for older PHP versions
132
+ // Since distillery doesn't check such a signature, this function is now much simpler
133
+ private function signedData($data){
134
+ return json_encode($data);
135
+ }
136
+
137
+ private function handleResponse($response, $ch){
138
+ $responseInfo = curl_getinfo($ch);
139
+ $responseCode = $responseInfo['http_code'];
140
+ $theResult = json_decode($response);
141
+
142
+ curl_close($ch);
143
+
144
+ // Unlike the rails API, distillery doesn't return such pretty statuses
145
+ // On successful creation, we get a JSON with the created product's fields:
146
+ // {"id":217127,"title":"Tori Tank","user_id":1055,"account_id":216,"public_contribution":false,"thumbnail_id":0,"inbox_thumbnail_id":0,"public_viewing":false,"description":null,"deleted_at":null,"public_token":null,"moderation":false,"email_slug":"A27EfF","campaign":false,"instructions":null,"action_link":null,"password":null,"has_password":false,"collect_email":false,"collect_custom_1":false,"collect_custom_1_field":null,"location_updated_at":null,"captions_updated_at":null,"redis_count":null,"num_inbox_photos":null,"unread_messages":null,"num_photos":null,"updated_dead_at":null,"live_update":false,"album_type":"product","display_options":{},"photos":[],"created_at":"2016-03-11 04:28:45.592","updated_at":"2016-03-11 04:28:45.592"}
147
+ // On product update, we just get a string that says:
148
+ // Product updated.
149
+ // Suppose we'll check the HTTP return code, but not expect a JSON 'status' field
150
+ if( !$this->isBetween( $responseCode, 200, 299 ) ){
151
+ throw new Exception("HTTP $responseCode response from API");
152
+ }else{
153
+ return $theResult;
154
+ }
155
+ }
156
+
157
+ private function isBetween($theNum, $low, $high){
158
+ if($theNum >= $low && $theNum <= $high){
159
+ return true;
160
+ }
161
+ else{
162
+ return false;
163
+ }
164
+ }
165
+ }
166
+
167
+ ?>
package.xml CHANGED
@@ -49,10 +49,10 @@ In addition to those fields, all of the events will include the following fields
49
  &#xD;
50
  3. Recognizing unique users&#xD;
51
  All of the users are now tracked using a 'distinct_user_hash' which is issued by Segment. To keep the 'distinct_user_hash' consistent throughout the period of time when the user is on the website - we use segment to only issue a distinct_user_hash relative to photos.pixlee.com. This helps us to recognize all users even if they we re-directed to a different domain.</notes>
52
- <authors><author><name>Awad Sayeed</name><user>awadsayeed</user><email>awad@pixleeteam.com</email></author></authors>
53
  <date>2016-03-14</date>
54
- <time>21:51:42</time>
55
- <contents><target name="magecommunity"><dir name="Pixlee"><dir name="Base"><dir name="Block"><dir name="Adminhtml"><dir name="System"><dir name="Config"><dir name="Form"><file name="Export.php" hash="a86d00b5a2e312a5bfdd856fd9ede257"/></dir></dir></dir></dir><file name="Gallery.php" hash="422d945772d1a38acf8ebc4f898971d0"/></dir><dir name="Helper"><file name="Data.php" hash="4f818cc47718aee113fa3c91d6fe5162"/></dir><dir name="Model"><file name="Observer.php" hash="a77b97332798cb88744b25ff30b7cda5"/><dir name="Product"><file name="Album.php" hash="1b415ff13e6fc9403e1149b327f9acb9"/></dir><dir name="Resource"><dir name="Product"><file name="Album.php" hash="a7f1e58ac017f183a2d1620d35645342"/></dir><file name="Setup.php" hash="a4f0721d4b19d19290e4999ef7ad327f"/></dir></dir><dir name="Test"><dir name="Helper"><file name="Data.php" hash="97b4546146d750033aed7c6855ea6327"/><dir name="fixtures"><file name="testGetUnexportedProducts.yaml" hash="9575424d3b1061d07181a8e9b2aaa6f4"/><file name="testIsActive.yaml" hash="53462b2a4bf02c846ae699633b24570c"/><file name="testIsInactive.yaml" hash="46909f781f699e14b389eed83b728433"/></dir></dir><file name="autoload.php" hash="05ed6c18a3ee3f523c242312de048eef"/></dir><dir name="controllers"><dir name="Pixlee"><file name="ExportController.php" hash="48eb932a2089646258d6b5ad6f744a5b"/></dir></dir><dir name="etc"><file name="config.xml" hash="45c1f57cae7589c9b9cf178a8316a15e"/><file name="system.xml" hash="07b4c9d8fb738e7a954d9c6e3ea15129"/></dir><dir name="sql"><dir name="pixlee_base_setup"><file name="mysql4-install-1.0.0.php" hash="219da3718bcbf86509c6be9609dd3ebb"/></dir></dir><file name="version.txt" hash="d925555f64cc9ab9d72f8702547e468d"/></dir></dir></target></contents>
56
  <compatible/>
57
  <dependencies><required><php><min>5.2.0</min><max>5.6.10</max></php></required></dependencies>
58
  </package>
49
  &#xD;
50
  3. Recognizing unique users&#xD;
51
  All of the users are now tracked using a 'distinct_user_hash' which is issued by Segment. To keep the 'distinct_user_hash' consistent throughout the period of time when the user is on the website - we use segment to only issue a distinct_user_hash relative to photos.pixlee.com. This helps us to recognize all users even if they we re-directed to a different domain.</notes>
52
+ <authors><author><name>Awad Sayeed</name><user>awadsayeed</user><email>awad@pixleeteam.com</email></author><author><name>Yunfan Luo</name><user>GANDAMU</user><email>yunfan@pixleeteam.com</email></author><author><name>Satnam Dhanoa</name><user>Satnam14</user><email>satnam@pixleeteam.com</email></author></authors>
53
  <date>2016-03-14</date>
54
+ <time>22:24:25</time>
55
+ <contents><target name="mageetc"><dir name="modules"><file name="Pixlee_Base.xml" hash="d61d4914e77a6f00ecad4d1c08a69c01"/></dir></target><target name="magecommunity"><dir name="Pixlee"><dir name="Base"><dir name="Block"><dir name="Adminhtml"><dir name="System"><dir name="Config"><dir name="Form"><file name="Export.php" hash="a86d00b5a2e312a5bfdd856fd9ede257"/></dir></dir></dir></dir><file name="Gallery.php" hash="422d945772d1a38acf8ebc4f898971d0"/></dir><dir name="Helper"><file name="Data.php" hash="4f818cc47718aee113fa3c91d6fe5162"/></dir><dir name="Model"><file name="Observer.php" hash="a77b97332798cb88744b25ff30b7cda5"/><dir name="Product"><file name="Album.php" hash="1b415ff13e6fc9403e1149b327f9acb9"/></dir><dir name="Resource"><dir name="Product"><file name="Album.php" hash="a7f1e58ac017f183a2d1620d35645342"/></dir><file name="Setup.php" hash="a4f0721d4b19d19290e4999ef7ad327f"/></dir></dir><dir name="Test"><dir name="Helper"><file name="Data.php" hash="97b4546146d750033aed7c6855ea6327"/><dir name="fixtures"><file name="testGetUnexportedProducts.yaml" hash="9575424d3b1061d07181a8e9b2aaa6f4"/><file name="testIsActive.yaml" hash="53462b2a4bf02c846ae699633b24570c"/><file name="testIsInactive.yaml" hash="46909f781f699e14b389eed83b728433"/></dir></dir><file name="autoload.php" hash="05ed6c18a3ee3f523c242312de048eef"/></dir><dir name="controllers"><dir name="Pixlee"><file name="ExportController.php" hash="48eb932a2089646258d6b5ad6f744a5b"/></dir></dir><dir name="etc"><file name="config.xml" hash="45c1f57cae7589c9b9cf178a8316a15e"/><file name="system.xml" hash="07b4c9d8fb738e7a954d9c6e3ea15129"/></dir><dir name="sql"><dir name="pixlee_base_setup"><file name="mysql4-install-1.0.0.php" hash="219da3718bcbf86509c6be9609dd3ebb"/></dir></dir><file name="version.txt" hash="d925555f64cc9ab9d72f8702547e468d"/></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><dir name="pixlee"><file name="base.xml" hash="e0fb83dce0f81138137a5d320de1dd96"/></dir></dir><dir name="template"><dir name="pixlee"><dir name="system"><dir name="config"><file name="export_button.phtml" hash="cbd180213a7c271bbf7b99ce8278764d"/></dir></dir></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><dir name="pixlee"><file name="gallery.xml" hash="4b8d94d02025fb4ecf5f32d554e5492f"/></dir></dir><dir name="template"><dir name="pixlee"><file name="gallery.phtml" hash="5c3bfd7f33ed99585d7bb7500aab05d3"/></dir></dir></dir></dir></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="pixlee"><file name="base.css" hash="22234fd8f1606d2d8a440d9a037c7fe4"/><file name="pixlee_logo_133x24.png" hash="af22b06f1fbffc0cf9e640926e59b736"/></dir></dir></dir></dir></target><target name="magelib"><dir name="Pixlee"><file name="Pixlee.php" hash="de26fabb97c19ce7aa79ac429fcf1506"/></dir></target></contents>
56
  <compatible/>
57
  <dependencies><required><php><min>5.2.0</min><max>5.6.10</max></php></required></dependencies>
58
  </package>
skin/adminhtml/default/default/pixlee/base.css ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ .pixlee-base > dl > dt.label > div {
2
+ height: 16px;
3
+ margin: 2px 0;
4
+ text-indent: -9999px;
5
+ background: url("pixlee_logo_133x24.png") no-repeat 0px 0px;
6
+ background-size: contain;
7
+ }
skin/adminhtml/default/default/pixlee/pixlee_logo_133x24.png ADDED
Binary file