diff --git a/core/Tracker/TrackerCodeGenerator.php b/core/Tracker/TrackerCodeGenerator.php index ac958e6102df16b4963a470a3909e0951a80f7bb..79b80e8bf1dd1618c184204a532d2c03d1fa72cb 100644 --- a/core/Tracker/TrackerCodeGenerator.php +++ b/core/Tracker/TrackerCodeGenerator.php @@ -46,7 +46,8 @@ class TrackerCodeGenerator $customCampaignKeywordParam = null, $doNotTrack = false, $disableCookies = false, - $trackNoScript = false + $trackNoScript = false, + $crossDomain = false ) { // changes made to this code should be mirrored in plugins/CoreAdminHome/javascripts/jsTrackingGenerator.js var generateJsCode @@ -62,9 +63,18 @@ class TrackerCodeGenerator if ($groupPageTitlesByDomain) { $options .= ' _paq.push(["setDocumentTitle", document.domain + "/" + document.title]);' . "\n"; } + if ($crossDomain) { + // When enabling cross domain, we also need to call `setDomains` + $mergeAliasUrls = true; + } if ($mergeSubdomains || $mergeAliasUrls) { $options .= $this->getJavascriptTagOptions($idSite, $mergeSubdomains, $mergeAliasUrls); } + + if ($crossDomain) { + $options .= ' _paq.push(["enableCrossDomainLinking"]);' . "\n"; + } + $maxCustomVars = CustomVariables::getNumUsableCustomVariables(); if ($visitorCustomVariables && count($visitorCustomVariables) > 0) { diff --git a/js/piwik.js b/js/piwik.js index 0c67497435172fad0d5ae8fcaee79b368cf654b2..95713ab13fa21ce73bf099c7db5e86d3ad49ee88 100644 --- a/js/piwik.js +++ b/js/piwik.js @@ -6025,7 +6025,7 @@ if (typeof window.Piwik !== 'object') { /** * Enables cross domain linking. By default, the visitor ID that identifies a unique visitor is stored in - * the browser's cookies. This means the cookie can only be accessed by pages on the same domain. + * the browser's first party cookies. This means the cookie can only be accessed by pages on the same domain. * If you own multiple domains and would like to track all the actions and pageviews of a specific visitor * into the same visit, you may enable cross domain linking. Whenever a user clicks on a link it will append * a URL parameter pk_vid to the clicked URL which consists of these parts: 16 char visitorId, a 10 character diff --git a/plugins/CoreAdminHome/angularjs/trackingcode/jstrackingcode.controller.js b/plugins/CoreAdminHome/angularjs/trackingcode/jstrackingcode.controller.js index 3758175751ebe89f91784193bea5f1f9abfdbab4..0eca1b96ad17eea19f2808c8e908eef87100a528 100644 --- a/plugins/CoreAdminHome/angularjs/trackingcode/jstrackingcode.controller.js +++ b/plugins/CoreAdminHome/angularjs/trackingcode/jstrackingcode.controller.js @@ -36,6 +36,7 @@ this.isLoading = false; this.customVars = []; this.siteUrls = {}; + this.hasManySiteUrls = false; this.maxCustomVariables = parseInt(angular.element('[name=numMaxCustomVariables]').val(), 10); this.canAddMoreCustomVariables = this.maxCustomVariables && this.maxCustomVariables > 0; @@ -48,6 +49,7 @@ var getSiteData = function (idSite, sectionSelect, callback) { // if data is already loaded, don't do an AJAX request if (self.siteUrls[idSite]) { + callback(); return; } @@ -85,6 +87,7 @@ customCampaignKeywordParam: null, doNotTrack: self.doNotTrack ? 1 : 0, disableCookies: self.disableCookies ? 1 : 0, + crossDomain: self.crossDomain ? 1 : 0, trackNoScript: self.trackNoScript ? 1: 0 }; @@ -116,6 +119,12 @@ return generateJsCodeAjax; }; + this.onCrossDomainToggle = function () { + if (this.crossDomain) { + this.trackAllAliases = true; + } + }; + this.addCustomVar = function () { if (this.canAddMoreCustomVariables) { this.customVars.push({name: '', value: ''}); @@ -136,6 +145,12 @@ getSiteData(this.site.id, '#js-code-options', function () { + self.hasManySiteUrls = self.siteUrls[self.site.id] && self.siteUrls[self.site.id].length > 1; + + if (!self.hasManySiteUrls) { + self.crossDomain = false; // we make sure to disable cross domain if it has only one url or less + } + var siteHost = getHostNameFromUrl(self.siteUrls[self.site.id][0]); $('.current-site-host').text(siteHost); diff --git a/plugins/CoreAdminHome/lang/en.json b/plugins/CoreAdminHome/lang/en.json index aee9217b07baa24a74bcc2ccf34cc0a5bd019c38..bc045654e7e3d055ca671bf9c48d28d24c216d5d 100644 --- a/plugins/CoreAdminHome/lang/en.json +++ b/plugins/CoreAdminHome/lang/en.json @@ -26,9 +26,11 @@ "JSTracking_CampaignNameParam": "Campaign Name parameter", "JSTracking_CodeNoteBeforeClosingHead": "Make sure this code is on every page of your website. We recommend to paste it immediately before the closing %1$s tag.", "JSTracking_CustomCampaignQueryParam": "Use custom query parameter names for the campaign name & keyword", + "JSTracking_CrossDomain": "By default, the visitor ID that identifies a unique visitor is stored in the browser's first party cookies which can only be accessed by pages on the same domain. Enabling cross domain linking lets you track all the actions and pageviews of a specific visitor into the same visit even when they view pages on several domains. Whenever a user clicks on a link to one of your website's alias URLs, it will append a URL parameter pk_vid forwarding the Visitor ID.", "JSTracking_CustomCampaignQueryParamDesc": "Note: %1$sPiwik will automatically detect Google Analytics parameters.%2$s", "JSTracking_DisableCookies": "Disable all tracking cookies", "JSTracking_DisableCookiesDesc": "Disables all first party cookies. Existing Piwik cookies for this website will be deleted on the next page view.", + "JSTracking_EnableCrossDomainLinking": "Enables cross domain linking", "JSTracking_EnableDoNotTrack": "Enable client side DoNotTrack detection", "JSTracking_EnableDoNotTrack_AlreadyEnabled": "Note: Server side DoNotTrack support has been enabled, so this option will have no effect.", "JSTracking_EnableDoNotTrackDesc": "So tracking requests will not be sent if visitors do not wish to be tracked.", diff --git a/plugins/CoreAdminHome/templates/trackingCodeGenerator.twig b/plugins/CoreAdminHome/templates/trackingCodeGenerator.twig index 19f693f5aa4774cf052aaee7c246ed3a47c622b5..71834c676ea402c4ac8ce877bcfb6f2048f41166 100644 --- a/plugins/CoreAdminHome/templates/trackingCodeGenerator.twig +++ b/plugins/CoreAdminHome/templates/trackingCodeGenerator.twig @@ -142,6 +142,19 @@ </div> </div> + {# cross domain support #} + <div id="jsCrossDomain" class="inline-help-node"> + {{ "CoreAdminHome_JSTracking_CrossDomain"|translate }} + </div> + + <div piwik-field uicontrol="checkbox" name="javascript-tracking-cross-domain" + ng-model="jsTrackingCode.crossDomain" + ng-change="jsTrackingCode.updateTrackingCode();jsTrackingCode.onCrossDomainToggle();" + disabled="jsTrackingCode.isLoading || !jsTrackingCode.hasManySiteUrls" + title="{{ 'CoreAdminHome_JSTracking_EnableCrossDomainLinking'|translate|e('html_attr') }}" + value="" inline-help="#jsCrossDomain"> + </div> + {# do not track support #} <div id="jsDoNotTrackInlineHelp" class="inline-help-node"> {{ 'CoreAdminHome_JSTracking_EnableDoNotTrackDesc'|translate }} @@ -153,7 +166,7 @@ <div piwik-field uicontrol="checkbox" name="javascript-tracking-do-not-track" ng-model="jsTrackingCode.doNotTrack" - ng-change="jsTrackingCode.updateTrackingCode()" + ng-change="jsTrackingCode.updateTrackingCode() " disabled="jsTrackingCode.isLoading" title="{{ 'CoreAdminHome_JSTracking_EnableDoNotTrack'|translate|e('html_attr') }}" value="" inline-help="#jsDoNotTrackInlineHelp"> diff --git a/plugins/SitesManager/API.php b/plugins/SitesManager/API.php index 49bda812f02879fac2e7a62042213bff4d118fe9..80bf65ac4302362cc95901ca7e63327108114555 100644 --- a/plugins/SitesManager/API.php +++ b/plugins/SitesManager/API.php @@ -105,7 +105,8 @@ class API extends \Piwik\Plugin\API public function getJavascriptTag($idSite, $piwikUrl = '', $mergeSubdomains = false, $groupPageTitlesByDomain = false, $mergeAliasUrls = false, $visitorCustomVariables = false, $pageCustomVariables = false, $customCampaignNameQueryParam = false, $customCampaignKeywordParam = false, - $doNotTrack = false, $disableCookies = false, $trackNoScript = false) + $doNotTrack = false, $disableCookies = false, $trackNoScript = false, + $crossDomain = false) { Piwik::checkUserHasViewAccess($idSite); @@ -125,7 +126,7 @@ class API extends \Piwik\Plugin\API $code = $generator->generate($idSite, $piwikUrl, $mergeSubdomains, $groupPageTitlesByDomain, $mergeAliasUrls, $visitorCustomVariables, $pageCustomVariables, $customCampaignNameQueryParam, $customCampaignKeywordParam, - $doNotTrack, $disableCookies, $trackNoScript); + $doNotTrack, $disableCookies, $trackNoScript, $crossDomain); $code = str_replace(array('<br>', '<br />', '<br/>'), '', $code); return $code; } diff --git a/tests/PHPUnit/Integration/Tracker/TrackerCodeGeneratorTest.php b/tests/PHPUnit/Integration/Tracker/TrackerCodeGeneratorTest.php index f596684d92dcc2d35075a1a7d9261a99d8170e83..f4eb5d799bd9158cc6a1696bf7c169e4290eddcc 100644 --- a/tests/PHPUnit/Integration/Tracker/TrackerCodeGeneratorTest.php +++ b/tests/PHPUnit/Integration/Tracker/TrackerCodeGeneratorTest.php @@ -9,6 +9,7 @@ namespace Piwik\Tests\Integration\Tracker; use Piwik\Piwik; +use Piwik\Plugins\SitesManager\SitesManager; use Piwik\Tests\Framework\TestCase\IntegrationTestCase; use Piwik\Tracker\TrackerCodeGenerator; @@ -21,18 +22,28 @@ class TrackerCodeGeneratorTest extends IntegrationTestCase { $generator = new TrackerCodeGenerator(); - $jsTag = $generator->generate($idSite = 1, $piwikUrl = 'http://localhost/piwik', + $urls = array( + 'http://localhost/piwik', + 'http://another-domain/piwik', + 'https://another-domain/piwik' + ); + $idSite = \Piwik\Plugins\SitesManager\API::getInstance()->addSite('Site name here <-->', $urls); + $jsTag = $generator->generate($idSite, 'http://piwik-server/piwik', $mergeSubdomains = true, $groupPageTitlesByDomain = true, $mergeAliasUrls = true, $visitorCustomVariables = array(array("name", "value"), array("name 2", "value 2")), $pageCustomVariables = array(array("page cvar", "page cvar value")), $customCampaignNameQueryParam = "campaignKey", $customCampaignKeywordParam = "keywordKey", - $doNotTrack = true, $disableCookies = false, $trackNoScript = true); + $doNotTrack = true, $disableCookies = false, $trackNoScript = true, + $crossDomain = true); $expected = "<!-- Piwik --> <script type="text/javascript"> var _paq = _paq || []; // tracker methods like "setCustomDimension" should be called before "trackPageView" _paq.push([\"setDocumentTitle\", document.domain + \"/\" + document.title]); + _paq.push([\"setCookieDomain\", \"*.localhost\"]); + _paq.push([\"setDomains\", [\"*.localhost/piwik\",\"*.another-domain/piwik\",\"*.another-domain/piwik\"]]); + _paq.push([\"enableCrossDomainLinking\"]); // you can set up to 5 custom variables for each visitor _paq.push([\"setCustomVariable\", 1, \"name\", \"value\", \"visit\"]); _paq.push([\"setCustomVariable\", 2, \"name 2\", \"value 2\", \"visit\"]); @@ -44,14 +55,14 @@ class TrackerCodeGeneratorTest extends IntegrationTestCase _paq.push(['trackPageView']); _paq.push(['enableLinkTracking']); (function() { - var u="//localhost/piwik/"; + var u="//piwik-server/piwik/"; _paq.push(['setTrackerUrl', u+'piwik.php']); _paq.push(['setSiteId', '1']); var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s); })(); </script> -<noscript><p><img src="//localhost/piwik/piwik.php?idsite=1&rec=1" style="border:0;" alt="" /></p></noscript> +<noscript><p><img src="//piwik-server/piwik/piwik.php?idsite=1&rec=1" style="border:0;" alt="" /></p></noscript> <!-- End Piwik Code --> "; diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png b/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png index 0e90886890b876b67692ac16887630e4f015405e..2890c755f5e8fa92652ea528555cc36e8cdbc0d7 100644 Binary files a/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png and b/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png differ