diff options
-rw-r--r-- | CHANGELOG.md | 3 | ||||
-rw-r--r-- | js/piwik.js | 12 | ||||
m--------- | misc/log-analytics | 0 | ||||
-rw-r--r-- | piwik.js | 2 | ||||
-rw-r--r-- | tests/javascript/index.php | 11 |
5 files changed, 23 insertions, 5 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index e1828ec642..ca005021df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ The Product Changelog at **[piwik.org/changelog](http://piwik.org/changelog)** l * Multiple JavaScript trackers can now be created easily via `_paq.push(['addTracker', piwikUrl, piwikSiteId])`. All tracking requests will be then sent to all added Piwik trackers. * It is possible to get an asynchronously created tracker instance (`addTracker`) via the method `Piwik.getAsyncTracker(optionalPiwikUrl, optionalPiwikSiteId)`. This allows you to get the tracker instance and to send different tracking requests to this Piwik instance and to configure it differently than other tracker instances. +### Internal change + * `piwik.js`: after an ecommerce order is tracked using `trackEcommerceOrder`, the items in the cart will now be removed from the JavaScript object. Calling `trackEcommerceCartUpdate` will not remove the items in the cart. + ## Piwik 2.16.1 ### New features diff --git a/js/piwik.js b/js/piwik.js index bed97aa65f..1079b7c859 100644 --- a/js/piwik.js +++ b/js/piwik.js @@ -3970,9 +3970,10 @@ if (typeof window.Piwik !== 'object') { lastEcommerceOrderTs, now = new Date(), items = [], - sku; + sku, + isEcommerceOrder = String(orderId).length; - if (String(orderId).length) { + if (isEcommerceOrder) { request += '&ec_id=' + encodeWrapper(orderId); // Record date of order in the visitor cookie lastEcommerceOrderTs = Math.round(now.getTime() / 1000); @@ -4028,6 +4029,10 @@ if (typeof window.Piwik !== 'object') { } request = getRequest(request, configCustomData, 'ecommerce', lastEcommerceOrderTs); sendRequest(request, configTrackerPause); + + if (isEcommerceOrder) { + ecommerceItems = {}; + } } function logEcommerceOrder(orderId, grandTotal, subTotal, tax, shipping, discount) { @@ -6320,6 +6325,7 @@ if (typeof window.Piwik !== 'object') { * Adds an item (product) that is in the current Cart or in the Ecommerce order. * This function is called for every item (product) in the Cart or the Order. * The only required parameter is sku. + * The items are deleted from this JavaScript object when the Ecommerce order is tracked via the method trackEcommerceOrder. * * @param string sku (required) Item's SKU Code. This is the unique identifier for the product. * @param string name (optional) Item's name @@ -6338,6 +6344,7 @@ if (typeof window.Piwik !== 'object') { * If the Ecommerce order contains items (products), you must call first the addEcommerceItem() for each item in the order. * All revenues (grandTotal, subTotal, tax, shipping, discount) will be individually summed and reported in Piwik reports. * Parameters orderId and grandTotal are required. For others, you can set to false if you don't need to specify them. + * After calling this method, items added to the cart will be removed from this JavaScript object. * * @param string|int orderId (required) Unique Order ID. * This will be used to count this order only once in the event the order page is reloaded several times. @@ -6356,6 +6363,7 @@ if (typeof window.Piwik !== 'object') { * Tracks a Cart Update (add item, remove item, update item). * On every Cart update, you must call addEcommerceItem() for each item (product) in the cart, including the items that haven't been updated since the last cart update. * Then you can call this function with the Cart grandTotal (typically the sum of all items' prices) + * Calling this method does not remove from this JavaScript object the items that were added to the cart via addEcommerceItem * * @param float grandTotal (required) Items (products) amount in the Cart */ diff --git a/misc/log-analytics b/misc/log-analytics -Subproject d9b4d68d5f08c0db5c80e942a63d19ffd9d16f3 +Subproject ca215c2b850c5429f6a62b96777b5f036706506 @@ -44,7 +44,7 @@ if(bh.length){cB[1]=bh}return cB}if(bh.length){cA=bh}else{if("0"===bx()){cA=""}e }function aj(){var cz=aT;aT=false;var cx=["id","ses","cvar","ref"];var cy,cA;for(cy=0;cy<cx.length;cy++){cA=aw(cx[cy]);if(0!==ah(cA)){bq(cA,aX,cg)}}aT=cz}function bv(cx){by=cx;ao()}function cw(cB){if(!cB||!N(cB)){return}var cA=[];var cz;for(cz in cB){if(Object.prototype.hasOwnProperty.call(cB,cz)){cA.push(cz)}}var cC={};cA.sort();var cx=cA.length;var cy;for(cy=0;cy<cx;cy++){cC[cA[cy]]=cB[cA[cy]]}return cC}function bF(){ct(aw("ses"),"*",bQ,aX,cg)}function bT(cz,cU,cV,cA){var cT,cy=new Date(),cH=Math.round(cy.getTime()/1000),cE,cS,cB=1024,c0,cI,cQ=at,cC=aw("ses"),cO=aw("ref"),cL=aw("cvar"),cM=ah(cC),cR=bf(),cX=aG||bg,cF,cx;if(aT){aj()}if(ca){return""}var cN=aA();if(!A(cA)){cA=""}var cK=x.characterSet||x.charset;if(!cK||cK.toLowerCase()==="utf-8"){cK=null}cF=cR[0];cx=cR[1];cE=cR[2];cS=cR[3];if(!cM){var cW=bQ/1000;if(!cN.lastVisitTs||(cH-cN.lastVisitTs)>cW){cN.visitCount++;cN.lastVisitTs=cN.currentVisitTs}if(!a1||!cF.length){for(cT in bS){if(Object.prototype.hasOwnProperty.call(bS,cT)){cF=M(cX,bS[cT]); if(cF.length){break}}}for(cT in ba){if(Object.prototype.hasOwnProperty.call(ba,cT)){cx=M(cX,ba[cT]);if(cx.length){break}}}}c0=c(aV);cI=cS.length?c(cS):"";if(c0.length&&!ay(c0)&&(!a1||!cI.length||ay(cI))){cS=aV}if(cS.length||cF.length){cE=cH;cR=[cF,cx,cE,bu(cS.slice(0,cB))];ct(cO,JSON2.stringify(cR),cm,aX,cg)}}cz+="&idsite="+by+"&rec=1&r="+String(Math.random()).slice(2,8)+"&h="+cy.getHours()+"&m="+cy.getMinutes()+"&s="+cy.getSeconds()+"&url="+n(bu(cX))+(aV.length?"&urlref="+n(bu(aV)):"")+((a4&&a4.length)?"&uid="+n(a4):"")+"&_id="+cN.uuid+"&_idts="+cN.createTs+"&_idvc="+cN.visitCount+"&_idn="+cN.newVisitor+(cF.length?"&_rcn="+n(cF):"")+(cx.length?"&_rck="+n(cx):"")+"&_refts="+cE+"&_viewts="+cN.lastVisitTs+(String(cN.lastEcommerceOrderTs).length?"&_ects="+cN.lastEcommerceOrderTs:"")+(String(cS).length?"&_ref="+n(bu(cS.slice(0,cB))):"")+(cK?"&cs="+n(cK):"")+"&send_image=0";for(cT in co){if(Object.prototype.hasOwnProperty.call(co,cT)){cz+="&"+cT+"="+co[cT]}}var cZ=[];if(cU){for(cT in cU){if(Object.prototype.hasOwnProperty.call(cU,cT)&&/^dimension\d+$/.test(cT)){var cD=cT.replace("dimension",""); cZ.push(parseInt(cD,10));cZ.push(String(cD));cz+="&"+cT+"="+cU[cT];delete cU[cT]}}}if(cU&&t(cU)){cU=null}for(cT in aU){if(Object.prototype.hasOwnProperty.call(aU,cT)){var cJ=(-1===cZ.indexOf(cT));if(cJ){cz+="&dimension"+cT+"="+aU[cT]}}}if(cU){cz+="&data="+n(JSON2.stringify(cU))}else{if(Y){cz+="&data="+n(JSON2.stringify(Y))}}function cG(c1,c2){var c3=JSON2.stringify(c1);if(c3.length>2){return"&"+c2+"="+n(c3)}return""}var cY=cw(bo);var cP=cw(bN);cz+=cG(cY,"cvar");cz+=cG(cP,"e_cvar");if(at){cz+=cG(at,"_cvar");for(cT in cQ){if(Object.prototype.hasOwnProperty.call(cQ,cT)){if(at[cT][0]===""||at[cT][1]===""){delete at[cT]}}}if(bj){ct(cL,JSON2.stringify(at),bQ,aX,cg)}}if(aE){if(bO){cz+=">_ms="+bO}else{if(g&&g.timing&&g.timing.requestStart&&g.timing.responseEnd){cz+=">_ms="+(g.timing.responseEnd-g.timing.requestStart)}}}cN.lastEcommerceOrderTs=A(cA)&&String(cA).length?cA:cN.lastEcommerceOrderTs;ao(cN);bF();cz+=R(cV);if(ci.length){cz+="&"+ci}if(s(bD)){cz=bD(cz)}return cz}bk=function aI(){var cx=new Date(); -if(ch+aH<=cx.getTime()){var cy=bT("ping=1",null,"ping");a9(cy,bc);return true}return false};function aY(cA,cz,cE,cB,cx,cH){var cC="idgoal=0",cD,cy=new Date(),cF=[],cG;if(String(cA).length){cC+="&ec_id="+n(cA);cD=Math.round(cy.getTime()/1000)}cC+="&revenue="+cz;if(String(cE).length){cC+="&ec_st="+cE}if(String(cB).length){cC+="&ec_tx="+cB}if(String(cx).length){cC+="&ec_sh="+cx}if(String(cH).length){cC+="&ec_dt="+cH}if(cj){for(cG in cj){if(Object.prototype.hasOwnProperty.call(cj,cG)){if(!A(cj[cG][1])){cj[cG][1]=""}if(!A(cj[cG][2])){cj[cG][2]=""}if(!A(cj[cG][3])||String(cj[cG][3]).length===0){cj[cG][3]=0}if(!A(cj[cG][4])||String(cj[cG][4]).length===0){cj[cG][4]=1}cF.push(cj[cG])}}cC+="&ec_items="+n(JSON2.stringify(cF))}cC=bT(cC,Y,"ecommerce",cD);a9(cC,bc)}function br(cx,cB,cA,cz,cy,cC){if(String(cx).length&&A(cB)){aY(cx,cB,cA,cz,cy,cC)}}function aZ(cx){if(A(cx)){aY("",cx,"","","","")}}function bs(cy,cA,cz){var cx=bT("action_name="+n(X(cy||aR)),cA,"log");a9(cx,bc,cz)}function aC(cz,cy){var cA,cx="(^| )(piwik[_-]"+cy; +if(ch+aH<=cx.getTime()){var cy=bT("ping=1",null,"ping");a9(cy,bc);return true}return false};function aY(cA,cz,cF,cB,cx,cI){var cD="idgoal=0",cE,cy=new Date(),cG=[],cH,cC=String(cA).length;if(cC){cD+="&ec_id="+n(cA);cE=Math.round(cy.getTime()/1000)}cD+="&revenue="+cz;if(String(cF).length){cD+="&ec_st="+cF}if(String(cB).length){cD+="&ec_tx="+cB}if(String(cx).length){cD+="&ec_sh="+cx}if(String(cI).length){cD+="&ec_dt="+cI}if(cj){for(cH in cj){if(Object.prototype.hasOwnProperty.call(cj,cH)){if(!A(cj[cH][1])){cj[cH][1]=""}if(!A(cj[cH][2])){cj[cH][2]=""}if(!A(cj[cH][3])||String(cj[cH][3]).length===0){cj[cH][3]=0}if(!A(cj[cH][4])||String(cj[cH][4]).length===0){cj[cH][4]=1}cG.push(cj[cH])}}cD+="&ec_items="+n(JSON2.stringify(cG))}cD=bT(cD,Y,"ecommerce",cE);a9(cD,bc);if(cC){cj={}}}function br(cx,cB,cA,cz,cy,cC){if(String(cx).length&&A(cB)){aY(cx,cB,cA,cz,cy,cC)}}function aZ(cx){if(A(cx)){aY("",cx,"","","","")}}function bs(cy,cA,cz){var cx=bT("action_name="+n(X(cy||aR)),cA,"log");a9(cx,bc,cz)}function aC(cz,cy){var cA,cx="(^| )(piwik[_-]"+cy; if(cz){for(cA=0;cA<cz.length;cA++){cx+="|"+cz[cA]}}cx+=")( |$)";return new RegExp(cx)}function ax(cx){return(ai&&cx&&0===String(cx).indexOf(ai))}function bU(cB,cx,cC,cy){if(ax(cx)){return 0}var cA=aC(be,"download"),cz=aC(aJ,"link"),cD=new RegExp("\\.("+cn.join("|")+")([?&#]|$)","i");if(cz.test(cB)){return"link"}if(cy||cA.test(cB)||cD.test(cx)){return"download"}if(cC){return 0}return"link"}function ac(cy){var cx;cx=cy.parentNode;while(cx!==null&&A(cx)){if(S.isLinkElement(cy)){break}cy=cx;cx=cy.parentNode}return cy}function cr(cC){cC=ac(cC);if(!S.hasNodeAttribute(cC,"href")){return}if(!A(cC.href)){return}var cB=S.getAttributeValueFromNode(cC,"href");if(ax(cB)){return}var cy=cC.pathname||bM(cC.href);var cD=cC.hostname||c(cC.href);var cE=cD.toLowerCase();var cz=cC.href.replace(cD,cE);var cA=new RegExp("^(javascript|vbscript|jscript|mocha|livescript|ecmascript|mailto|tel):","i");if(!cA.test(cz)){var cx=bU(cC.className,cz,ab(cE,cy),S.hasNodeAttribute(cC,"download"));if(cx){return{type:cx,href:cz} }}}function ar(cx,cy,cz,cA){var cB=p.buildInteractionRequestParams(cx,cy,cz,cA);if(!cB){return}return bT(cB,null,"contentInteraction")}function b7(cz,cA,cE,cx,cy){if(!A(cz)){return}if(ax(cz)){return cz}var cC=p.toAbsoluteUrl(cz);var cB="redirecturl="+n(cC)+"&";cB+=ar(cA,cE,cx,(cy||cz));var cD="&";if(ai.indexOf("?")<0){cD="?"}return ai+cD+cB}function aM(cx,cy){if(!cx||!cy){return false}var cz=p.findTargetNode(cx);if(p.shouldIgnoreInteraction(cz)){return false}cz=p.findTargetNodeNoDefault(cx);if(cz&&!L(cz,cy)){return false}return true}function bV(cz,cy,cB){if(!cz){return}var cx=p.findParentContentNode(cz);if(!cx){return}if(!aM(cx,cz)){return}var cA=p.buildContentBlock(cx);if(!cA){return}if(!cA.target&&cB){cA.target=cB}return p.buildInteractionRequestParams(cy,cA.name,cA.piece,cA.target)}function az(cy){if(!bC||!bC.length){return false}var cx,cz;for(cx=0;cx<bC.length;cx++){cz=bC[cx];if(cz&&cz.name===cy.name&&cz.piece===cy.piece&&cz.target===cy.target){return true}}return false}function a8(cA){if(!cA){return false }var cD=p.findTargetNode(cA);if(!cD||p.shouldIgnoreInteraction(cD)){return false}var cE=cr(cD);if(cp&&cE&&cE.type){return false}if(S.isLinkElement(cD)&&S.hasNodeAttributeWithValue(cD,"href")){var cx=String(S.getAttributeValueFromNode(cD,"href"));if(0===cx.indexOf("#")){return false}if(ax(cx)){return true}if(!p.isUrlToCurrentDomain(cx)){return false}var cB=p.buildContentBlock(cA);if(!cB){return}var cz=cB.name;var cF=cB.piece;var cC=cB.target;if(!S.hasNodeAttributeWithValue(cD,p.CONTENT_TARGET_ATTR)||cD.wasContentTargetAttrReplaced){cD.wasContentTargetAttrReplaced=true;cC=p.toAbsoluteUrl(cx);S.setAnyAttribute(cD,p.CONTENT_TARGET_ATTR,cC)}var cy=b7(cx,"click",cz,cF,cC);p.setHrefAttribute(cD,cy);return true}return false}function ap(cy){if(!cy||!cy.length){return}var cx;for(cx=0;cx<cy.length;cx++){a8(cy[cx])}}function aB(cx){return function(cy){if(!cx){return}var cB=p.findParentContentNode(cx);var cC;if(cy){cC=cy.target||cy.srcElement}if(!cC){cC=cx}if(!aM(cB,cC)){return}bI(bc);if(S.isLinkElement(cx)&&S.hasNodeAttributeWithValue(cx,"href")&&S.hasNodeAttributeWithValue(cx,p.CONTENT_TARGET_ATTR)){var cz=S.getAttributeValueFromNode(cx,"href"); diff --git a/tests/javascript/index.php b/tests/javascript/index.php index f796b93cf3..bd592f7cf1 100644 --- a/tests/javascript/index.php +++ b/tests/javascript/index.php @@ -3033,7 +3033,7 @@ if ($mysql) { }); test("tracking", function() { - expect(117); + expect(118); // Prevent Opera and HtmlUnit from performing the default action (i.e., load the href URL) var stopEvent = function (evt) { @@ -3287,8 +3287,12 @@ if ($mysql) { tracker3.addEcommerceItem("SKU NO PRICE NO QUANTITY", "PRODUCT NAME 3", "CATEGORY", "", "" ); tracker3.addEcommerceItem("SKU ONLY" ); tracker3.trackEcommerceCartUpdate( 555.55 ); + tracker3.trackEcommerceOrder( "ORDER ID YES", 666.66, 333, 222, 111, 1 ); + // the same order tracked once more, should have no items + tracker3.trackEcommerceOrder( "ORDER WITHOUT ANY ITEM", 777, 444, 222, 111, 1 ); + // do not track tracker3.setDoNotTrack(false); @@ -3351,7 +3355,7 @@ if ($mysql) { xhr.open("GET", "piwik.php?requests=" + getToken(), false); xhr.send(null); results = xhr.responseText; - equal( (/<span\>([0-9]+)\<\/span\>/.exec(results))[1], "35", "count tracking events" ); + equal( (/<span\>([0-9]+)\<\/span\>/.exec(results))[1], "36", "count tracking events" ); // firing callback ok( trackLinkCallbackFired, "trackLink() callback fired" ); @@ -3428,6 +3432,9 @@ if ($mysql) { // Cart update ok( /idgoal=0&revenue=555.55&ec_items=%5B%5B%22SKU%20PRODUCT%22%2C%22random%22%2C%22random%20PRODUCT%20CATEGORY%22%2C11.1111%2C2%5D%2C%5B%22SKU%20ONLY%20SKU%22%2C%22%22%2C%22%22%2C0%2C1%5D%2C%5B%22SKU%20ONLY%20NAME%22%2C%22PRODUCT%20NAME%202%22%2C%22%22%2C0%2C1%5D%2C%5B%22SKU%20NO%20PRICE%20NO%20QUANTITY%22%2C%22PRODUCT%20NAME%203%22%2C%22CATEGORY%22%2C0%2C1%5D%2C%5B%22SKU%20ONLY%22%2C%22%22%2C%22%22%2C0%2C1%5D%5D/.test( results ), "logEcommerceCartUpdate() with items" ); + // Ecommerce order recorded twice, but each order empties the cart/list of items, so this order is empty of items + ok( /idgoal=0&ec_id=ORDER%20WITHOUT%20ANY%20ITEM&revenue=777&ec_st=444&ec_tx=222&ec_sh=111&ec_dt=1&ec_items=%5B%5D/.test( results ), "logEcommerceOrder() called twice, second time has no item" ); + // parameters inserted by plugin hooks ok( /testlog/.test( results ), "plugin hook log" ); ok( /testlink/.test( results ), "plugin hook link" ); |