diff options
author | Thomas Steur <tsteur@users.noreply.github.com> | 2018-11-27 01:01:39 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-27 01:01:39 +0300 |
commit | d3b46b1d837a11617e79fd3da7e546697fddd2fd (patch) | |
tree | c794ddea0f4599bca3f83617689cdc2b7d19f06b /plugins/Referrers | |
parent | ad992c423b477581372ce4ce49853d198c153cc2 (diff) |
Add campaign url builder widget (#13546)
* add campaign url builder
* add missing translations
* apply review changes
* fix tests
Diffstat (limited to 'plugins/Referrers')
16 files changed, 382 insertions, 4 deletions
diff --git a/plugins/Referrers/Categories/CampaignUrlBuilderSubcategory.php b/plugins/Referrers/Categories/CampaignUrlBuilderSubcategory.php new file mode 100644 index 0000000000..271b820ad3 --- /dev/null +++ b/plugins/Referrers/Categories/CampaignUrlBuilderSubcategory.php @@ -0,0 +1,19 @@ +<?php +/** + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Plugins\Referrers\Categories; + +use Piwik\Category\Subcategory; + +class CampaignUrlBuilderSubcategory extends Subcategory +{ + protected $categoryId = 'Referrers_Referrers'; + protected $id = 'Referrers_URLCampaignBuilder'; + protected $order = 21; + +} diff --git a/plugins/Referrers/Referrers.php b/plugins/Referrers/Referrers.php index a279ecea91..3f31af95a5 100644 --- a/plugins/Referrers/Referrers.php +++ b/plugins/Referrers/Referrers.php @@ -8,10 +8,8 @@ */ namespace Piwik\Plugins\Referrers; -use Piwik\ArchiveProcessor; use Piwik\Common; use Piwik\Piwik; -use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable; use Piwik\Plugins\SitesManager\SiteUrls; /** @@ -24,17 +22,52 @@ require_once PIWIK_INCLUDE_PATH . '/plugins/Referrers/functions.php'; class Referrers extends \Piwik\Plugin { /** - * @see Piwik\Plugin::registerEvents + * @see \Piwik\Plugin::registerEvents */ public function registerEvents() { return array( 'Insights.addReportToOverview' => 'addReportToInsightsOverview', 'Request.getRenamedModuleAndAction' => 'renameDeprecatedModuleAndAction', - 'Tracker.setTrackerCacheGeneral' => 'setTrackerCacheGeneral' + 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys', + 'Tracker.setTrackerCacheGeneral' => 'setTrackerCacheGeneral', + 'AssetManager.getJavaScriptFiles' => 'getJsFiles', + 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles', ); } + public function getStylesheetFiles(&$stylesheets) + { + $stylesheets[] = 'plugins/Referrers/angularjs/campaign-builder/campaign-builder.directive.less'; + } + + public function getClientSideTranslationKeys(&$translationKeys) + { + $translationKeys[] = 'General_Required2'; + $translationKeys[] = 'General_Clear'; + $translationKeys[] = 'Actions_ColumnPageURL'; + $translationKeys[] = 'CoreAdminHome_JSTracking_CampaignNameParam'; + $translationKeys[] = 'CoreAdminHome_JSTracking_CampaignKwdParam'; + $translationKeys[] = 'Referrers_CampaignSource'; + $translationKeys[] = 'Referrers_CampaignSourceHelp'; + $translationKeys[] = 'Referrers_CampaignContent'; + $translationKeys[] = 'Referrers_CampaignContentHelp'; + $translationKeys[] = 'Referrers_CampaignMedium'; + $translationKeys[] = 'Referrers_CampaignMediumHelp'; + $translationKeys[] = 'Referrers_CampaignPageUrlHelp'; + $translationKeys[] = 'Referrers_CampaignNameHelp'; + $translationKeys[] = 'Referrers_CampaignKeywordHelp'; + $translationKeys[] = 'Referrers_URLCampaignBuilderResult'; + $translationKeys[] = 'Referrers_GenerateUrl'; + $translationKeys[] = 'Goals_Optional'; + } + + public function getJsFiles(&$jsFiles) + { + $jsFiles[] = 'plugins/Referrers/angularjs/campaign-builder/campaign-builder.controller.js'; + $jsFiles[] = 'plugins/Referrers/angularjs/campaign-builder/campaign-builder.directive.js'; + } + public function setTrackerCacheGeneral(&$cacheContent) { $siteUrls = new SiteUrls(); diff --git a/plugins/Referrers/Widgets/GetCampaignUrlBuilder.php b/plugins/Referrers/Widgets/GetCampaignUrlBuilder.php new file mode 100644 index 0000000000..bfc3308f1b --- /dev/null +++ b/plugins/Referrers/Widgets/GetCampaignUrlBuilder.php @@ -0,0 +1,48 @@ +<?php +/** + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Plugins\Referrers\Widgets; + +use Piwik\Common; +use Piwik\Piwik; +use Piwik\Plugin; +use Piwik\Widget\WidgetConfig; +use Piwik\SettingsPiwik; + +class GetCampaignUrlBuilder extends \Piwik\Widget\Widget +{ + public static function configure(WidgetConfig $config) + { + $config->setCategoryId('Referrers_Referrers'); + $config->setSubcategoryId('Referrers_URLCampaignBuilder'); + $config->setName('Referrers_URLCampaignBuilder'); + + $idSite = self::getIdSite(); + if (!Piwik::isUserHasViewAccess($idSite)) { + $config->disable(); + } + } + + private static function getIdSite() + { + return Common::getRequestVar('idSite', 0, 'int'); + } + + public function render() + { + $idSite = self::getIdSite(); + Piwik::checkUserHasViewAccess($idSite); + + $hasExtraPlugin = Plugin\Manager::getInstance()->isPluginActivated('MarketingCampaignsReporting'); + + return $this->renderTemplate('campaignBuilder', array( + 'hasExtraPlugin' => (int)$hasExtraPlugin + )); + } + +} diff --git a/plugins/Referrers/angularjs/campaign-builder/campaign-builder.controller.js b/plugins/Referrers/angularjs/campaign-builder/campaign-builder.controller.js new file mode 100644 index 0000000000..9de53df4fa --- /dev/null +++ b/plugins/Referrers/angularjs/campaign-builder/campaign-builder.controller.js @@ -0,0 +1,76 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +(function () { + angular.module('piwikApp').controller('CampaignBuilderController', CampaignBuilderController); + + CampaignBuilderController.$inject = ['$scope']; + + function CampaignBuilderController($scope) { + this.hasExtraPlugin = $scope.hasExtraPlugin; + + this.reset = function () { + this.websiteUrl = ''; + this.campaignName = ''; + this.campaignKeyword = ''; + this.campaignSource = ''; + this.campaignMedium = ''; + this.campaignContent = ''; + this.generatedUrl = ''; + }; + + this.generateUrl = function () { + this.generatedUrl = String(this.websiteUrl); + + if (this.generatedUrl.indexOf('http') !== 0) { + this.generatedUrl = 'https://' + this.generatedUrl.trim(); + } + + var urlHashPos = this.generatedUrl.indexOf('#'); + var urlHash = ''; + if (urlHashPos >= 0) { + urlHash = this.generatedUrl.substr(urlHashPos); + this.generatedUrl = this.generatedUrl.substr(0, urlHashPos); + } + + if (this.generatedUrl.indexOf('/', 10) < 0 && this.generatedUrl.indexOf("?") < 0) { + this.generatedUrl += '/'; + } + + var campaignName = encodeURIComponent(this.campaignName.trim()); + + if (this.generatedUrl.indexOf('?') > 0 || this.generatedUrl.indexOf('#') > 0) { + this.generatedUrl += '&'; + } else { + this.generatedUrl += '?'; + } + + this.generatedUrl += 'pk_campaign='+campaignName; + + if (this.campaignKeyword) { + this.generatedUrl += '&pk_kwd='+encodeURIComponent(this.campaignKeyword.trim()); + } + + if (this.campaignSource) { + this.generatedUrl += '&pk_source='+encodeURIComponent(this.campaignSource.trim()); + } + + if (this.campaignMedium) { + this.generatedUrl += '&pk_medium='+encodeURIComponent(this.campaignMedium.trim()); + } + + if (this.campaignContent) { + this.generatedUrl += '&pk_content='+encodeURIComponent(this.campaignContent.trim()); + } + + this.generatedUrl += urlHash; + + $('#urlCampaignBuilderResult').effect("highlight", {}, 1500); + }; + + this.reset(); + } +})();
\ No newline at end of file diff --git a/plugins/Referrers/angularjs/campaign-builder/campaign-builder.directive.html b/plugins/Referrers/angularjs/campaign-builder/campaign-builder.directive.html new file mode 100644 index 0000000000..d80de154b7 --- /dev/null +++ b/plugins/Referrers/angularjs/campaign-builder/campaign-builder.directive.html @@ -0,0 +1,60 @@ +<div class="campaignUrlBuilder"> + + <form> + <div piwik-field uicontrol="text" name="websiteurl" + title="{{'Actions_ColumnPageURL'|translate}} ({{ 'General_Required2'|translate }})" + ng-model="campaignBuilder.websiteUrl" + inline-help="{{'Referrers_CampaignPageUrlHelp'|translate}}"> + </div> + + <div piwik-field uicontrol="text" name="campaignname" + title="{{ 'CoreAdminHome_JSTracking_CampaignNameParam'|translate }} ({{ 'General_Required2'|translate }})" + ng-model="campaignBuilder.campaignName" + inline-help="{{'Referrers_CampaignNameHelp'|translate}}"> + </div> + + <div piwik-field uicontrol="text" name="campaignkeyword" + title="{{ 'CoreAdminHome_JSTracking_CampaignKwdParam'|translate }}" + ng-model="campaignBuilder.campaignKeyword" + inline-help="{{'Goals_Optional'|translate}} {{'Referrers_CampaignKeywordHelp'|translate}}"> + </div> + + <div piwik-field uicontrol="text" name="campaignsource" + title="{{ 'Referrers_CampaignSource'|translate }}" + ng-model="campaignBuilder.campaignSource" + ng-show="campaignBuilder.hasExtraPlugin" + inline-help="{{'Goals_Optional'|translate}} {{'Referrers_CampaignSourceHelp'|translate}}"> + </div> + + <div piwik-field uicontrol="text" name="campaignmedium" + title="{{ 'Referrers_CampaignMedium'|translate }}" + ng-model="campaignBuilder.campaignMedium" + ng-show="campaignBuilder.hasExtraPlugin" + inline-help="{{'Goals_Optional'|translate}} {{'Referrers_CampaignMediumHelp'|translate}}"> + </div> + + <div piwik-field uicontrol="text" name="campaigncontent" + title="{{ 'Referrers_CampaignContent'|translate }}" + ng-model="campaignBuilder.campaignContent" + ng-show="campaignBuilder.hasExtraPlugin" + inline-help="{{'Goals_Optional'|translate}} {{'Referrers_CampaignContentHelp'|translate}}"> + </div> + + <div piwik-save-button + class="generateCampaignUrl" + onconfirm="campaignBuilder.generateUrl()" + disabled="!campaignBuilder.websiteUrl || !campaignBuilder.campaignName" + value="{{ 'Referrers_GenerateUrl'|translate }}"> + </div> + <div piwik-save-button + class="resetCampaignUrl" + onconfirm="campaignBuilder.reset()" + value="{{ 'General_Clear'|translate }}"> + </div> + + <div ng-show="campaignBuilder.generatedUrl"> + <h3>{{'Referrers_URLCampaignBuilderResult'|translate}}</h3> + <pre piwik-select-on-focus id="urlCampaignBuilderResult"><code ng-bind="campaignBuilder.generatedUrl"></code></pre> + </div> + </form> +</div>
\ No newline at end of file diff --git a/plugins/Referrers/angularjs/campaign-builder/campaign-builder.directive.js b/plugins/Referrers/angularjs/campaign-builder/campaign-builder.directive.js new file mode 100644 index 0000000000..a14fbd33da --- /dev/null +++ b/plugins/Referrers/angularjs/campaign-builder/campaign-builder.directive.js @@ -0,0 +1,44 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +/** + * Usage: + * <div matomo-campaign-builder> + */ +(function () { + angular.module('piwikApp').directive('matomoCampaignBuilder', matomoCampaignBuilder); + + matomoCampaignBuilder.$inject = ['piwik']; + + function matomoCampaignBuilder(piwik){ + var defaults = { + hasExtraPlugin: true + }; + + return { + restrict: 'A', + scope: { + hasExtraPlugin: '<' + }, + templateUrl: 'plugins/Referrers/angularjs/campaign-builder/campaign-builder.directive.html?cb=' + piwik.cacheBuster, + controller: 'CampaignBuilderController', + controllerAs: 'campaignBuilder', + compile: function (element, attrs) { + + for (var index in defaults) { + if (defaults.hasOwnProperty(index) && attrs[index] === undefined) { + attrs[index] = defaults[index]; + } + } + + return function (scope, element, attrs) { + + }; + } + }; + } +})();
\ No newline at end of file diff --git a/plugins/Referrers/angularjs/campaign-builder/campaign-builder.directive.less b/plugins/Referrers/angularjs/campaign-builder/campaign-builder.directive.less new file mode 100644 index 0000000000..353b8f71a3 --- /dev/null +++ b/plugins/Referrers/angularjs/campaign-builder/campaign-builder.directive.less @@ -0,0 +1,3 @@ +.campaignUrlBuilder { + margin-bottom: 30px; +}
\ No newline at end of file diff --git a/plugins/Referrers/lang/en.json b/plugins/Referrers/lang/en.json index d3807dc886..914984dd97 100644 --- a/plugins/Referrers/lang/en.json +++ b/plugins/Referrers/lang/en.json @@ -5,6 +5,15 @@ "CampaignsDocumentation": "Visitors that came to your website as the result of a campaign. %1$s See the %2$s report for more details.", "CampaignsReportDocumentation": "This report shows which campaigns led visitors to your website. %1$s For more information about tracking campaigns, read the %2$scampaigns documentation on piwik.org%3$s", "ColumnCampaign": "Campaign", + "CampaignPageUrlHelp": "The URL of the page that this campaign goes to, for example 'http://example.org/offer.html'.", + "CampaignNameHelp": "Choose a name that describes what the campaign is created for and that distinguishes your campaign from your other campaigns. For example 'Email-SummerDeals' or 'PaidAds-SummerDeals'.", + "CampaignKeywordHelp": "If you have multiple campaigns with the same name, you can distinguish these campaigns by specifying a keyword or a sub-category.", + "CampaignSource": "Campaign Source", + "CampaignSourceHelp": "Used to track the source of the campaign such as 'newsletter' for your email marketing, 'affiliate', or the name of the website displaying your ads.", + "CampaignContent": "Campaign content", + "CampaignContentHelp": "This parameter is often used when you are testing multiple ads, and would include the name of each ad to see which was most effective for driving traffic.", + "CampaignMedium": "Campaign Medium", + "CampaignMediumHelp": "Used to describe the marketing activity, for example 'PPC' for a pay-per-click campaign, or 'SEM' for a paid search ads, or 'review' to track a product review on an affiliate site.", "ColumnSearchEngine": "Search Engine", "ColumnSocial": "Social network", "ColumnWebsite": "Website", @@ -45,6 +54,10 @@ "TypeSocialNetworks": "%s from social networks", "TypeWebsites": "%s from websites", "UsingNDistinctUrls": "(using %s distinct urls)", + "GenerateUrl": "Generate URL", + "URLCampaignBuilder": "Campaign URL Builder", + "URLCampaignBuilderIntro": "The %1$sURL Builder tool%2$s lets you generate URLs ready to use for Tracking Campaigns in Matomo. See the documentation about %3$sCampaign Tracking%4$s for more information.", + "URLCampaignBuilderResult": "Generated URL that you can copy paste in your Campaigns, Email newsletter, Facebook Ads or tweets:", "ViewAllReferrers": "View all Referrers", "ViewReferrersBy": "View Referrers by %s", "Websites": "Websites", diff --git a/plugins/Referrers/templates/campaignBuilder.twig b/plugins/Referrers/templates/campaignBuilder.twig new file mode 100644 index 0000000000..0978d67226 --- /dev/null +++ b/plugins/Referrers/templates/campaignBuilder.twig @@ -0,0 +1,4 @@ +<div class="widgetBody"> + <p>{{ 'Referrers_URLCampaignBuilderIntro'|translate('<a href="https://matomo.org/docs/tracking-campaigns-url-builder/" rel="noreferrer noopener">', '</a>', '<a href="https://matomo.org/docs/tracking-campaigns/" rel="noreferrer noopener">', '</a>')|raw }}</p> + <div matomo-campaign-builder has-extra-plugin="{{ hasExtraPlugin|e('html_attr') }}"></div> +</div>
\ No newline at end of file diff --git a/plugins/Referrers/tests/UI/.gitignore b/plugins/Referrers/tests/UI/.gitignore new file mode 100644 index 0000000000..f39be478e7 --- /dev/null +++ b/plugins/Referrers/tests/UI/.gitignore @@ -0,0 +1,2 @@ +/processed-ui-screenshots +/screenshot-diffs
\ No newline at end of file diff --git a/plugins/Referrers/tests/UI/CampaignBuilder_spec.js b/plugins/Referrers/tests/UI/CampaignBuilder_spec.js new file mode 100644 index 0000000000..b3cd6e4bbd --- /dev/null +++ b/plugins/Referrers/tests/UI/CampaignBuilder_spec.js @@ -0,0 +1,64 @@ +/*! + * Piwik - free/libre analytics platform + * + * Screenshot integration tests. + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +describe("CampaignBuilder", function () { + this.timeout(0); + + var url = '?module=Widgetize&action=iframe&widget=1&moduleToWidgetize=Referrers&actionToWidgetize=getCampaignUrlBuilder&idSite=1&period=day&date=yesterday&disableLink=1&widget=1'; + + before(function () { + testEnvironment.pluginsToLoad = ['Referrers']; + testEnvironment.save(); + }); + + function captureUrlBuilder(done, screenshotName, theTest) + { + expect.screenshot(screenshotName).to.be.captureSelector('.campaignUrlBuilder', theTest, done); + } + + function ensureHighlightEffectIsGone(page) + { + page.wait(2000); + } + + function generateUrl(page) + { + page.click('.generateCampaignUrl'); + ensureHighlightEffectIsGone(page); + } + + it('should load the url builder', function (done) { + expect.screenshot('loaded').to.be.capture(function (page) { + page.load(url); + }, done); + }); + + it('generate simple url with url and campaign name', function (done) { + captureUrlBuilder(done, 'generate_url_nokeyword', function (page) { + page.sendKeys('#websiteurl', 'https://www.example.com/foo/bar?x=1&y=2#foobarbaz'); + page.sendKeys('#campaignname', 'My2018Campaign-Test'); + generateUrl(page); + }); + }); + + it('can reset form', function (done) { + captureUrlBuilder(done, 'generate_url_reset', function (page) { + page.click('.resetCampaignUrl'); + }); + }); + + it('generate simple url with url and campaign name and keyword', function (done) { + captureUrlBuilder(done, 'generate_url_withkeyword', function (page) { + page.sendKeys('#websiteurl', 'www.example.com'); + page.sendKeys('#campaignname', 'MyAwesome<&§Name'); + page.sendKeys('#campaignkeyword', 'MyAwesome<&§Keyword'); + generateUrl(page); + }); + }); +});
\ No newline at end of file diff --git a/plugins/Referrers/tests/UI/expected-screenshots/.gitkeep b/plugins/Referrers/tests/UI/expected-screenshots/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/plugins/Referrers/tests/UI/expected-screenshots/.gitkeep diff --git a/plugins/Referrers/tests/UI/expected-screenshots/CampaignBuilder_generate_url_nokeyword.png b/plugins/Referrers/tests/UI/expected-screenshots/CampaignBuilder_generate_url_nokeyword.png new file mode 100644 index 0000000000..c8d9acbde9 --- /dev/null +++ b/plugins/Referrers/tests/UI/expected-screenshots/CampaignBuilder_generate_url_nokeyword.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e687daa106b5ef7a602f603eeb9021806cdbe86bfa40cda09bc97f245bd7d11c +size 84232 diff --git a/plugins/Referrers/tests/UI/expected-screenshots/CampaignBuilder_generate_url_reset.png b/plugins/Referrers/tests/UI/expected-screenshots/CampaignBuilder_generate_url_reset.png new file mode 100644 index 0000000000..9519895dcf --- /dev/null +++ b/plugins/Referrers/tests/UI/expected-screenshots/CampaignBuilder_generate_url_reset.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1d043e42b23f1a9e3297951e2215a4cb6688d1c784620324681d635ff9b86f29 +size 55025 diff --git a/plugins/Referrers/tests/UI/expected-screenshots/CampaignBuilder_generate_url_withkeyword.png b/plugins/Referrers/tests/UI/expected-screenshots/CampaignBuilder_generate_url_withkeyword.png new file mode 100644 index 0000000000..1163b8a669 --- /dev/null +++ b/plugins/Referrers/tests/UI/expected-screenshots/CampaignBuilder_generate_url_withkeyword.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a9af1c708b5685fe96b483bca016a66df410fcdee4b4b1611ab1a8dbb2846e98 +size 86483 diff --git a/plugins/Referrers/tests/UI/expected-screenshots/CampaignBuilder_loaded.png b/plugins/Referrers/tests/UI/expected-screenshots/CampaignBuilder_loaded.png new file mode 100644 index 0000000000..adecb06c00 --- /dev/null +++ b/plugins/Referrers/tests/UI/expected-screenshots/CampaignBuilder_loaded.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bc4db3e124c8f83ec456bf2b23dcc0d019204914ac2ca173a74ee69d80e5b192 +size 69971 |