diff options
author | Thomas Steur <thomas.steur@googlemail.com> | 2014-08-21 15:18:50 +0400 |
---|---|---|
committer | Thomas Steur <thomas.steur@googlemail.com> | 2014-08-21 15:18:50 +0400 |
commit | d44cce7e3b49c8a74d30b0b35e042491409a7f45 (patch) | |
tree | 3aa9fb227b390bbd28fe261edf8e670028b4e7b3 | |
parent | 0610a6d428c3d4a725483678a9c5700a4888ea06 (diff) |
refs #4996 track content pieces and display a content report under action and added a widget
-rw-r--r-- | core/Plugin/Manager.php | 1 | ||||
-rw-r--r-- | core/Tracker/Action.php | 7 | ||||
-rw-r--r-- | core/Tracker/Request.php | 5 | ||||
-rw-r--r-- | misc/internal-docs/content-tracking.md | 10 | ||||
-rw-r--r-- | plugins/Contents/API.php | 43 | ||||
-rw-r--r-- | plugins/Contents/Actions/ActionContent.php | 55 | ||||
-rw-r--r-- | plugins/Contents/Columns/ContentName.php | 55 | ||||
-rw-r--r-- | plugins/Contents/Columns/ContentPiece.php | 56 | ||||
-rw-r--r-- | plugins/Contents/Columns/ContentTarget.php | 56 | ||||
-rw-r--r-- | plugins/Contents/Contents.php | 28 | ||||
-rw-r--r-- | plugins/Contents/README.md | 18 | ||||
-rw-r--r-- | plugins/Contents/Reports/Base.php | 19 | ||||
-rw-r--r-- | plugins/Contents/Reports/GetContents.php | 67 | ||||
-rw-r--r-- | plugins/Contents/lang/en.json | 9 | ||||
-rw-r--r-- | plugins/Contents/plugin.json | 13 | ||||
-rw-r--r-- | plugins/Contents/screenshots/.gitkeep | 0 |
16 files changed, 439 insertions, 3 deletions
diff --git a/core/Plugin/Manager.php b/core/Plugin/Manager.php index 114d79a1d6..b6ed33342a 100644 --- a/core/Plugin/Manager.php +++ b/core/Plugin/Manager.php @@ -80,6 +80,7 @@ class Manager extends Singleton 'ExamplePluginTemplate', 'ExampleTracker', 'ExampleReport', + 'Contents' ); // Themes bundled with core package, disabled by default diff --git a/core/Tracker/Action.php b/core/Tracker/Action.php index b3ca851f61..6d46987252 100644 --- a/core/Tracker/Action.php +++ b/core/Tracker/Action.php @@ -36,10 +36,15 @@ abstract class Action const TYPE_EVENT_ACTION = 11; const TYPE_EVENT_NAME = 12; + const TYPE_CONTENT = 13; // Alias TYPE_CONTENT_PIECE + const TYPE_CONTENT_PIECE = 13; + const TYPE_CONTENT_NAME = 14; + const TYPE_CONTENT_TARGET = 15; + const DB_COLUMN_CUSTOM_FLOAT = 'custom_float'; private static $factoryPriority = array( - self::TYPE_PAGE_URL, self::TYPE_SITE_SEARCH, self::TYPE_EVENT, self::TYPE_OUTLINK, self::TYPE_DOWNLOAD + self::TYPE_PAGE_URL, self::TYPE_SITE_SEARCH, self::TYPE_EVENT, self::TYPE_CONTENT, self::TYPE_OUTLINK, self::TYPE_DOWNLOAD ); /** diff --git a/core/Tracker/Request.php b/core/Tracker/Request.php index 98057f6ccc..97469727c7 100644 --- a/core/Tracker/Request.php +++ b/core/Tracker/Request.php @@ -287,6 +287,11 @@ class Request 'search_cat' => array(false, 'string'), 'search_count' => array(-1, 'int'), 'gt_ms' => array(-1, 'int'), + + // Content + 'c_p' => array('', 'string'), + 'c_n' => array('', 'string'), + 'c_t' => array('', 'string'), ); if (!isset($supportedParams[$name])) { diff --git a/misc/internal-docs/content-tracking.md b/misc/internal-docs/content-tracking.md index 1f5ba0568f..09fb9d65a5 100644 --- a/misc/internal-docs/content-tracking.md +++ b/misc/internal-docs/content-tracking.md @@ -2,14 +2,18 @@ This is the technical concept for implementing content tracking. We won't plan anything to death but a little bit of thinking upfront makes sense :) Feel free to contribute and let us know if you have any objections! If your thoughts are not technical please comment on the actual issue [#4996](#4996). +## Naming +* Plugin name: Content +* Content name - The name of the content visible in reports +* Content piece - eg a video file, image file, text, ... +* Content target - a clicked url, a started video, any "conversion"... Are we always assuming it is a click or can it be a hover or drag/drop, ...? + ## Tagging of the content piece declarative In HTML... ## Tracking the impressions Impressions are logically not really events and I don't think it makes sense to use them here. It would also make it harder to analyze events when they are mixed with pieces of content. -* New url parameter like `content` which contains serialized JSON like - [{"c": "content", "n": "name", "u": "url"}, ...] * Saving in database? * New column `id_action_content_url` and `id_action_content_piece` in `log_link_visit_action`. For name `id_action_name` can be reused? * Would we need a new column for each piece of content in action table to make archiver work? --> would result in many! columns @@ -17,6 +21,8 @@ Impressions are logically not really events and I don't think it makes sense to * or would we store the pieces serialized as JSON in a `content` column? I don't know anything about the archiver but I think it wouldn't work at all * or would we create an action entry for each piece of content? --> yes I think! * New Action class that handles type content +* New url parameters like `c_p`, `c_n` and `c_u` for piece of content, name and url. Maybe instead of `c_u` would be better `c_t` for target which is more generic. Sending a JSON array would not work since we cannot log multiple actions in one tracking request. They have to be sent using bulk tracking instead. + * `c_c` and `c_n` would be required, `c_t` not as for instance a piece of content does not necessarily have a target (hard to measure a click ratio in this case?) Would a piece of content have maybe custom variables etc? diff --git a/plugins/Contents/API.php b/plugins/Contents/API.php new file mode 100644 index 0000000000..da5c6f1081 --- /dev/null +++ b/plugins/Contents/API.php @@ -0,0 +1,43 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Plugins\Contents; + +use Piwik\DataTable; +use Piwik\DataTable\Row; + +/** + * API for plugin Contents + * + * @method static \Piwik\Plugins\Contents\API getInstance() + */ +class API extends \Piwik\Plugin\API +{ + + /** + * Another example method that returns a data table. + * @param int $idSite + * @param string $period + * @param string $date + * @param bool|string $segment + * @return DataTable + */ + public function getContents($idSite, $period, $date, $segment = false) + { + $table = new DataTable(); + + $table->addRowFromArray(array(Row::COLUMNS => array( + 'label' => 'My banner', + 'nb_impressions' => 50, + 'nb_conversions' => 5, + 'conversion_rate' => '10%' + ))); + + return $table; + } +} diff --git a/plugins/Contents/Actions/ActionContent.php b/plugins/Contents/Actions/ActionContent.php new file mode 100644 index 0000000000..0fba02a698 --- /dev/null +++ b/plugins/Contents/Actions/ActionContent.php @@ -0,0 +1,55 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ + +namespace Piwik\Plugins\Contents\Actions; + +use Piwik\Tracker\Action; +use Piwik\Tracker\Request; +use Piwik\Tracker; + +/** + * A content is composed of a name, an actual piece of content, and optionally a target. + */ +class ActionContent extends Action +{ + public function __construct(Request $request) + { + parent::__construct(Action::TYPE_CONTENT, $request); + + $url = $request->getParam('url'); + $this->setActionUrl($url); + } + + public static function shouldHandle(Request $request) + { + $piece = $request->getParam('c_p'); + $name = $request->getParam('c_n'); + + return !empty($piece) && !empty($name); + } + + protected function getActionsToLookup() + { + return array( + 'idaction_url' => $this->getUrlAndType() + ); + } + + // Do not track this Event URL as Entry/Exit Page URL (leave the existing entry/exit) + public function getIdActionUrlForEntryAndExitIds() + { + return false; + } + + // Do not track this Event Name as Entry/Exit Page Title (leave the existing entry/exit) + public function getIdActionNameForEntryAndExitIds() + { + return false; + } +} diff --git a/plugins/Contents/Columns/ContentName.php b/plugins/Contents/Columns/ContentName.php new file mode 100644 index 0000000000..21af924e4b --- /dev/null +++ b/plugins/Contents/Columns/ContentName.php @@ -0,0 +1,55 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Plugins\Contents\Columns; + +use Piwik\Piwik; +use Piwik\Plugin\Dimension\ActionDimension; +use Piwik\Plugins\Contents\Actions\ActionContent; +use Piwik\Plugins\Actions\Segment; +use Piwik\Tracker\Action; +use Piwik\Tracker\Request; + +class ContentName extends ActionDimension +{ + protected $columnName = 'idaction_name'; + + protected function configureSegments() + { + $segment = new Segment(); + $segment->setSegment('contentName'); + $segment->setName('Contents_ContentName'); + $this->addSegment($segment); + } + + public function getName() + { + return Piwik::translate('Contents_ContentName'); + } + + public function getActionId() + { + return Action::TYPE_CONTENT_NAME; + } + + public function onLookupAction(Request $request, Action $action) + { + if (!($action instanceof ActionContent)) { + return false; + } + + $contentName = $request->getParam('c_n'); + $contentName = trim($contentName); + + if (strlen($contentName) > 0) { + return $contentName; + } + + return false; + } +}
\ No newline at end of file diff --git a/plugins/Contents/Columns/ContentPiece.php b/plugins/Contents/Columns/ContentPiece.php new file mode 100644 index 0000000000..c64b3b5660 --- /dev/null +++ b/plugins/Contents/Columns/ContentPiece.php @@ -0,0 +1,56 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Plugins\Contents\Columns; + +use Piwik\Piwik; +use Piwik\Plugin\Dimension\ActionDimension; +use Piwik\Plugins\Actions\Segment; +use Piwik\Plugins\Contents\Actions\ActionContent; +use Piwik\Tracker\Action; +use Piwik\Tracker\Request; + +class ContentPiece extends ActionDimension +{ + protected $columnName = 'idaction_content_piece'; + protected $columnType = 'INTEGER(10) UNSIGNED DEFAULT NULL'; + + protected function configureSegments() + { + $segment = new Segment(); + $segment->setSegment('contentPiece'); + $segment->setName('Contents_ContentPiece'); + $this->addSegment($segment); + } + + public function getName() + { + return Piwik::translate('Contents_ContentPiece'); + } + + public function getActionId() + { + return Action::TYPE_CONTENT_PIECE; + } + + public function onLookupAction(Request $request, Action $action) + { + if (!($action instanceof ActionContent)) { + return false; + } + + $contentPiece = $request->getParam('c_p'); + $contentPiece = trim($contentPiece); + + if (strlen($contentPiece) > 0) { + return $contentPiece; + } + + return false; + } +}
\ No newline at end of file diff --git a/plugins/Contents/Columns/ContentTarget.php b/plugins/Contents/Columns/ContentTarget.php new file mode 100644 index 0000000000..17abb9f1a5 --- /dev/null +++ b/plugins/Contents/Columns/ContentTarget.php @@ -0,0 +1,56 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Plugins\Contents\Columns; + +use Piwik\Piwik; +use Piwik\Plugin\Dimension\ActionDimension; +use Piwik\Plugins\Actions\Segment; +use Piwik\Plugins\Contents\Actions\ActionContent; +use Piwik\Tracker\Action; +use Piwik\Tracker\Request; + +class ContentTarget extends ActionDimension +{ + protected $columnName = 'idaction_content_target'; + protected $columnType = 'INTEGER(10) UNSIGNED DEFAULT NULL'; + + protected function configureSegments() + { + $segment = new Segment(); + $segment->setSegment('contentTarget'); + $segment->setName('Contents_ContentTarget'); + $this->addSegment($segment); + } + + public function getName() + { + return Piwik::translate('Contents_ContentTarget'); + } + + public function getActionId() + { + return Action::TYPE_CONTENT_TARGET; + } + + public function onLookupAction(Request $request, Action $action) + { + if (!($action instanceof ActionContent)) { + return false; + } + + $contentTarget = $request->getParam('c_t'); + $contentTarget = trim($contentTarget); + + if (strlen($contentTarget) > 0) { + return $contentTarget; + } + + return false; + } +}
\ No newline at end of file diff --git a/plugins/Contents/Contents.php b/plugins/Contents/Contents.php new file mode 100644 index 0000000000..df54017d68 --- /dev/null +++ b/plugins/Contents/Contents.php @@ -0,0 +1,28 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Plugins\Contents; + +class Contents extends \Piwik\Plugin +{ + /** + * @see Piwik\Plugin::getListHooksRegistered + */ + public function getListHooksRegistered() + { + return array( + 'Metrics.getDefaultMetricTranslations' => 'addMetricTranslations' + ); + } + + public function addMetricTranslations(&$translations) + { + $translations['nb_impressions'] = 'Contents_Impressions'; + } + +} diff --git a/plugins/Contents/README.md b/plugins/Contents/README.md new file mode 100644 index 0000000000..dc2db01387 --- /dev/null +++ b/plugins/Contents/README.md @@ -0,0 +1,18 @@ +# Piwik Contents Plugin + +## Description + +Add your plugin description here. + +## FAQ + +__My question?__ +My answer + +## Changelog + +Here goes the changelog text. + +## Support + +Please direct any feedback to ...
\ No newline at end of file diff --git a/plugins/Contents/Reports/Base.php b/plugins/Contents/Reports/Base.php new file mode 100644 index 0000000000..84540699f9 --- /dev/null +++ b/plugins/Contents/Reports/Base.php @@ -0,0 +1,19 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Plugins\Contents\Reports; + +use Piwik\Plugin\Report; + +abstract class Base extends Report +{ + protected function init() + { + $this->category = 'General_Actions'; + } +} diff --git a/plugins/Contents/Reports/GetContents.php b/plugins/Contents/Reports/GetContents.php new file mode 100644 index 0000000000..1d4205d956 --- /dev/null +++ b/plugins/Contents/Reports/GetContents.php @@ -0,0 +1,67 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Plugins\Contents\Reports; + +use Piwik\Piwik; +use Piwik\Plugin\Report; +use Piwik\Plugin\ViewDataTable; + +use Piwik\Plugins\Contents\Columns\ContentName; +use Piwik\View; + +/** + * This class defines a new report. + * + * See {@link http://developer.piwik.org/api-reference/Piwik/Plugin/Report} for more information. + */ +class GetContents extends Base +{ + protected function init() + { + parent::init(); + + $this->name = Piwik::translate('ContentsName'); + $this->dimension = null; + $this->documentation = Piwik::translate('ContentsDocumentation'); + $this->dimension = new ContentName(); + $this->order = 35; + + $this->menuTitle = 'Contents_Contents'; + $this->widgetTitle = $this->menuTitle; + + $this->metrics = array('nb_impressions', 'nb_conversions', 'conversion_rate'); + } + + /** + * Here you can configure how your report should be displayed. For instance whether your report supports a search + * etc. You can also change the default request config. For instance change how many rows are displayed by default. + * + * @param ViewDataTable $view + */ + public function configureView(ViewDataTable $view) + { + if (!empty($this->dimension)) { + $view->config->addTranslations(array('label' => $this->dimension->getName())); + } + + $view->config->columns_to_display = array_merge(array('label'), $this->metrics); + $view->requestConfig->filter_sort_column = 'nb_impressions'; + } + + /** + * Here you can define related reports that will be shown below the reports. Just return an array of related + * report instances if there are any. + * + * @return \Piwik\Plugin\Report[] + */ + public function getRelatedReports() + { + return array(); // eg return array(new XyzReport()); + } +} diff --git a/plugins/Contents/lang/en.json b/plugins/Contents/lang/en.json new file mode 100644 index 0000000000..33f9434073 --- /dev/null +++ b/plugins/Contents/lang/en.json @@ -0,0 +1,9 @@ +{ + "Contents":{ + "Impressions":"Impressions", + "ContentName":"Content Name", + "ContentPiece":"Content Piece", + "ContentTarget":"Content Target", + "Contents":"Contents" + } +}
\ No newline at end of file diff --git a/plugins/Contents/plugin.json b/plugins/Contents/plugin.json new file mode 100644 index 0000000000..dbfd2b145f --- /dev/null +++ b/plugins/Contents/plugin.json @@ -0,0 +1,13 @@ +{ + "name": "Contents", + "version": "0.1.0", + "description": "Content and banner tracking", + "theme": false, + "authors": [ + { + "name": "Piwik", + "email": "", + "homepage": "" + } + ] +}
\ No newline at end of file diff --git a/plugins/Contents/screenshots/.gitkeep b/plugins/Contents/screenshots/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/plugins/Contents/screenshots/.gitkeep |