forked from matomo-org/matomo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Tracking Actions refactoring to accomodate Custom Events matomo-org#472
- Loading branch information
Showing
15 changed files
with
666 additions
and
577 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
<?php | ||
/** | ||
* Piwik - Open source web analytics | ||
* | ||
* @link http://piwik.org | ||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later | ||
* | ||
* @category Piwik | ||
* @package Piwik | ||
*/ | ||
|
||
namespace Piwik\Tracker; | ||
|
||
use Piwik\Tracker; | ||
|
||
/** | ||
* This class represents a download or an outlink. | ||
* This is a particular type of Action: it has no 'name' | ||
* | ||
* @package Piwik\Tracker | ||
*/ | ||
class ActionClickUrl extends Action | ||
{ | ||
function __construct($type, $url, Request $request) | ||
{ | ||
parent::__construct($type, $request); | ||
$this->setActionUrl($url); | ||
} | ||
|
||
function getActionNameType() | ||
{ | ||
return null; | ||
} | ||
|
||
function writeDebugInfo() | ||
{ | ||
parent::writeDebugInfo(); | ||
|
||
if (self::detectActionIsOutlinkOnAliasHost($this, $this->request->getIdSite())) { | ||
Common::printDebug("INFO: The outlink URL host is one of the known host for this website. "); | ||
} | ||
} | ||
|
||
/** | ||
* Detect whether action is an outlink given host aliases | ||
* | ||
* @param ActionInterface $action | ||
* @return bool true if the outlink the visitor clicked on points to one of the known hosts for this website | ||
*/ | ||
public static function detectActionIsOutlinkOnAliasHost(ActionInterface $action, $idSite) | ||
{ | ||
if ($action->getActionType() != ActionInterface::TYPE_OUTLINK) { | ||
return false; | ||
} | ||
$decodedActionUrl = $action->getActionUrl(); | ||
$actionUrlParsed = @parse_url($decodedActionUrl); | ||
if (!isset($actionUrlParsed['host'])) { | ||
return false; | ||
} | ||
return Visit::isHostKnownAliasHost($actionUrlParsed['host'], $idSite); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
<?php | ||
/** | ||
* Piwik - Open source web analytics | ||
* | ||
* @link http://piwik.org | ||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later | ||
* | ||
* @category Piwik | ||
* @package Piwik | ||
*/ | ||
|
||
namespace Piwik\Tracker; | ||
|
||
use Piwik\Tracker; | ||
|
||
use Piwik\Config; | ||
|
||
class ActionPageview extends Action | ||
{ | ||
protected $timeGeneration = false; | ||
|
||
function __construct($url, Request $request) | ||
{ | ||
parent::__construct(ActionInterface::TYPE_PAGE_URL, $request); | ||
|
||
$this->setActionUrl($url); | ||
|
||
$actionName = $request->getParam('action_name'); | ||
$actionName = $this->cleanupActionName($actionName); | ||
$this->setActionName($actionName); | ||
|
||
$this->timeGeneration = $this->request->getPageGenerationTime(); | ||
} | ||
|
||
function getActionCustomValue() | ||
{ | ||
return $this->request->getPageGenerationTime(); | ||
} | ||
|
||
protected function cleanupActionName($actionName) | ||
{ | ||
// get the delimiter, by default '/'; BC, we read the old action_category_delimiter first (see #1067) | ||
$actionCategoryDelimiter = isset(Config::getInstance()->General['action_category_delimiter']) | ||
? Config::getInstance()->General['action_category_delimiter'] | ||
: Config::getInstance()->General['action_url_category_delimiter']; | ||
|
||
// create an array of the categories delimited by the delimiter | ||
$split = explode($actionCategoryDelimiter, $actionName); | ||
|
||
// trim every category | ||
$split = array_map('trim', $split); | ||
|
||
// remove empty categories | ||
$split = array_filter($split, 'strlen'); | ||
|
||
// rebuild the name from the array of cleaned categories | ||
$actionName = implode($actionCategoryDelimiter, $split); | ||
return $actionName; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,249 @@ | ||
<?php | ||
/** | ||
* Piwik - Open source web analytics | ||
* | ||
* @link http://piwik.org | ||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later | ||
* | ||
* @category Piwik | ||
* @package Piwik | ||
*/ | ||
|
||
namespace Piwik\Tracker; | ||
|
||
use Piwik\Common; | ||
use Piwik\Config; | ||
use Piwik\Tracker; | ||
use Piwik\UrlHelper; | ||
|
||
class ActionSiteSearch extends Action | ||
{ | ||
const CVAR_KEY_SEARCH_CATEGORY = '_pk_scat'; | ||
const CVAR_KEY_SEARCH_COUNT = '_pk_scount'; | ||
const CVAR_INDEX_SEARCH_CATEGORY = '4'; | ||
const CVAR_INDEX_SEARCH_COUNT = '5'; | ||
private $searchCategory = false; | ||
private $searchCount = false; | ||
|
||
function __construct($url, Request $request) | ||
{ | ||
parent::__construct(ActionInterface::TYPE_SITE_SEARCH, $request); | ||
$this->originalUrl = $url; | ||
} | ||
|
||
function getActionCustomValue() | ||
{ | ||
return $this->request->getPageGenerationTime(); | ||
} | ||
|
||
function isSearchDetected() | ||
{ | ||
$siteSearch = $this->detectSiteSearch($this->originalUrl); | ||
|
||
if(empty($siteSearch)) { | ||
return false; | ||
} | ||
|
||
list($actionName,$url, $category, $count) = $siteSearch; | ||
|
||
if (!empty($category)) { | ||
$this->searchCategory = trim($category); | ||
} | ||
if ($count !== false) { | ||
$this->searchCount = $count; | ||
} | ||
$this->setActionName($actionName); | ||
$this->setActionUrl($url); | ||
} | ||
|
||
// FIXMEA replace by getNameAndType | ||
protected function getActionNameType() | ||
{ | ||
return ActionInterface::TYPE_SITE_SEARCH; | ||
} | ||
|
||
public function getIdActionUrl() | ||
{ | ||
// Site Search, by default, will not track URL. We do not want URL to appear as "Page URL not defined" | ||
// so we specifically set it to NULL in the table (the archiving query does IS NOT NULL) | ||
if (empty(Config::getInstance()->Tracker['action_sitesearch_record_url'])) { | ||
return null; | ||
} | ||
return parent::getIdActionUrl(); | ||
} | ||
|
||
public function getCustomVariables() | ||
{ | ||
$customVariables = parent::getCustomVariables(); | ||
|
||
// Enrich Site Search actions with Custom Variables, overwriting existing values | ||
if (!empty($this->searchCategory)) { | ||
if (!empty($customVariables['custom_var_k' . self::CVAR_INDEX_SEARCH_CATEGORY])) { | ||
Common::printDebug("WARNING: Overwriting existing Custom Variable in slot " . self::CVAR_INDEX_SEARCH_CATEGORY . " for this page view"); | ||
} | ||
$customVariables['custom_var_k' . self::CVAR_INDEX_SEARCH_CATEGORY] = self::CVAR_KEY_SEARCH_CATEGORY; | ||
$customVariables['custom_var_v' . self::CVAR_INDEX_SEARCH_CATEGORY] = Request::truncateCustomVariable($this->searchCategory); | ||
} | ||
if ($this->searchCount !== false) { | ||
if (!empty($customVariables['custom_var_k' . self::CVAR_INDEX_SEARCH_COUNT])) { | ||
Common::printDebug("WARNING: Overwriting existing Custom Variable in slot " . self::CVAR_INDEX_SEARCH_COUNT . " for this page view"); | ||
} | ||
$customVariables['custom_var_k' . self::CVAR_INDEX_SEARCH_COUNT] = self::CVAR_KEY_SEARCH_COUNT; | ||
$customVariables['custom_var_v' . self::CVAR_INDEX_SEARCH_COUNT] = (int)$this->searchCount; | ||
} | ||
return $customVariables; | ||
} | ||
|
||
public function isSiteSearchDetected($originalUrl) | ||
{ | ||
return true; | ||
} | ||
|
||
protected function detectSiteSearchFromUrl($website, $parsedUrl) | ||
{ | ||
$doRemoveSearchParametersFromUrl = false; | ||
$separator = '&'; | ||
$count = $actionName = $categoryName = false; | ||
|
||
$keywordParameters = isset($website['sitesearch_keyword_parameters']) | ||
? $website['sitesearch_keyword_parameters'] | ||
: array(); | ||
$queryString = (!empty($parsedUrl['query']) ? $parsedUrl['query'] : '') . (!empty($parsedUrl['fragment']) ? $separator . $parsedUrl['fragment'] : ''); | ||
$parametersRaw = UrlHelper::getArrayFromQueryString($queryString); | ||
|
||
// strtolower the parameter names for smooth site search detection | ||
$parameters = array(); | ||
foreach ($parametersRaw as $k => $v) { | ||
$parameters[Common::mb_strtolower($k)] = $v; | ||
} | ||
// decode values if they were sent from a client using another charset | ||
$pageEncoding = $this->request->getParam('cs'); | ||
PageUrl::reencodeParameters($parameters, $pageEncoding); | ||
|
||
// Detect Site Search keyword | ||
foreach ($keywordParameters as $keywordParameterRaw) { | ||
$keywordParameter = Common::mb_strtolower($keywordParameterRaw); | ||
if (!empty($parameters[$keywordParameter])) { | ||
$actionName = $parameters[$keywordParameter]; | ||
break; | ||
} | ||
} | ||
|
||
if (empty($actionName)) { | ||
return false; | ||
} | ||
|
||
$categoryParameters = isset($website['sitesearch_category_parameters']) | ||
? $website['sitesearch_category_parameters'] | ||
: array(); | ||
|
||
foreach ($categoryParameters as $categoryParameterRaw) { | ||
$categoryParameter = Common::mb_strtolower($categoryParameterRaw); | ||
if (!empty($parameters[$categoryParameter])) { | ||
$categoryName = $parameters[$categoryParameter]; | ||
break; | ||
} | ||
} | ||
|
||
if (isset($parameters['search_count']) | ||
&& $this->isValidSearchCount($parameters['search_count']) | ||
) { | ||
$count = $parameters['search_count']; | ||
} | ||
// Remove search kwd from URL | ||
if ($doRemoveSearchParametersFromUrl) { | ||
// @see excludeQueryParametersFromUrl() | ||
// Excluded the detected parameters from the URL | ||
$parametersToExclude = array($categoryParameterRaw, $keywordParameterRaw); | ||
$parsedUrl['query'] = UrlHelper::getQueryStringWithExcludedParameters(UrlHelper::getArrayFromQueryString($parsedUrl['query']), $parametersToExclude); | ||
$parsedUrl['fragment'] = UrlHelper::getQueryStringWithExcludedParameters(UrlHelper::getArrayFromQueryString($parsedUrl['fragment']), $parametersToExclude); | ||
} | ||
$url = UrlHelper::getParseUrlReverse($parsedUrl); | ||
if (is_array($actionName)) { | ||
$actionName = reset($actionName); | ||
} | ||
$actionName = trim(urldecode($actionName)); | ||
if (empty($actionName)) { | ||
return false; | ||
} | ||
if (is_array($categoryName)) { | ||
$categoryName = reset($categoryName); | ||
} | ||
$categoryName = trim(urldecode($categoryName)); | ||
return array($url, $actionName, $categoryName, $count); | ||
} | ||
|
||
protected function isValidSearchCount($count) | ||
{ | ||
return is_numeric($count) && $count >= 0; | ||
} | ||
|
||
protected function detectSiteSearch($originalUrl) | ||
{ | ||
$website = Cache::getCacheWebsiteAttributes($this->request->getIdSite()); | ||
if (empty($website['sitesearch'])) { | ||
Common::printDebug("Internal 'Site Search' tracking is not enabled for this site. "); | ||
return false; | ||
} | ||
|
||
$actionName = $url = $categoryName = $count = false; | ||
$doTrackUrlForSiteSearch = !empty(Config::getInstance()->Tracker['action_sitesearch_record_url']); | ||
|
||
$originalUrl = PageUrl::cleanupUrl($originalUrl); | ||
|
||
// Detect Site search from Tracking API parameters rather than URL | ||
$searchKwd = $this->request->getParam('search'); | ||
if (!empty($searchKwd)) { | ||
$actionName = $searchKwd; | ||
if ($doTrackUrlForSiteSearch) { | ||
$url = $originalUrl; | ||
} | ||
$isCategoryName = $this->request->getParam('search_cat'); | ||
if (!empty($isCategoryName)) { | ||
$categoryName = $isCategoryName; | ||
} | ||
$isCount = $this->request->getParam('search_count'); | ||
if ($this->isValidSearchCount($isCount)) { | ||
$count = $isCount; | ||
} | ||
} | ||
|
||
if (empty($actionName)) { | ||
$parsedUrl = @parse_url($originalUrl); | ||
|
||
// Detect Site Search from URL query parameters | ||
if (!empty($parsedUrl['query']) || !empty($parsedUrl['fragment'])) { | ||
// array($url, $actionName, $categoryName, $count); | ||
$searchInfo = $this->detectSiteSearchFromUrl($website, $parsedUrl); | ||
if (!empty($searchInfo)) { | ||
list ($url, $actionName, $categoryName, $count) = $searchInfo; | ||
} | ||
} | ||
} | ||
|
||
if (empty($actionName)) { | ||
Common::printDebug("(this is not a Site Search request)"); | ||
return false; | ||
} | ||
|
||
Common::printDebug("Detected Site Search keyword '$actionName'. "); | ||
if (!empty($categoryName)) { | ||
Common::printDebug("- Detected Site Search Category '$categoryName'. "); | ||
} | ||
if ($count !== false) { | ||
Common::printDebug("- Search Results Count was '$count'. "); | ||
} | ||
if ($url != $originalUrl) { | ||
Common::printDebug("NOTE: The Page URL was changed / removed, during the Site Search detection, was '$originalUrl', now is '$url'"); | ||
} | ||
|
||
return array( | ||
$actionName, | ||
$url, | ||
$categoryName, | ||
$count | ||
); | ||
} | ||
|
||
|
||
} |
Oops, something went wrong.