PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.2.0
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.2.0
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / core / Metrics.php
matomo / app / core Last commit date
API 1 year ago Access 1 year ago Application 1 year ago Archive 1 year ago ArchiveProcessor 1 year ago Archiver 2 years ago AssetManager 1 year ago Auth 1 year ago Category 2 years ago Changes 1 year ago CliMulti 1 year ago Columns 1 year ago Concurrency 1 year ago Config 1 year ago Container 1 year ago CronArchive 1 year ago DataAccess 1 year ago DataFiles 2 years ago DataTable 1 year ago Db 1 year ago DeviceDetector 1 year ago Email 2 years ago Exception 1 year ago Http 1 year ago Intl 1 year ago Log 2 years ago Mail 1 year ago Measurable 1 year ago Menu 1 year ago Metrics 1 year ago Notification 1 year ago Period 1 year ago Plugin 1 year ago ProfessionalServices 1 year ago Report 1 year ago ReportRenderer 1 year ago Scheduler 1 year ago Segment 1 year ago Session 1 year ago Settings 1 year ago Tracker 1 year ago Translation 1 year ago Twig 1 year ago UpdateCheck 1 year ago Updater 1 year ago Updates 1 year ago Validators 1 year ago View 1 year ago ViewDataTable 1 year ago Visualization 1 year ago Widget 1 year ago .htaccess 2 years ago Access.php 1 year ago Archive.php 1 year ago ArchiveProcessor.php 1 year ago AssetManager.php 1 year ago Auth.php 2 years ago AuthResult.php 2 years ago BaseFactory.php 2 years ago Cache.php 2 years ago CacheId.php 1 year ago CliMulti.php 1 year ago Common.php 1 year ago Config.php 1 year ago Console.php 1 year ago Context.php 2 years ago Cookie.php 1 year ago CronArchive.php 1 year ago DI.php 1 year ago DataArray.php 1 year ago DataTable.php 1 year ago Date.php 1 year ago Db.php 1 year ago DbHelper.php 1 year ago Development.php 1 year ago ErrorHandler.php 1 year ago EventDispatcher.php 1 year ago ExceptionHandler.php 1 year ago FileIntegrity.php 1 year ago Filechecks.php 1 year ago Filesystem.php 1 year ago FrontController.php 1 year ago Http.php 1 year ago IP.php 1 year ago Log.php 2 years ago LogDeleter.php 1 year ago Mail.php 1 year ago Metrics.php 1 year ago NoAccessException.php 2 years ago Nonce.php 1 year ago Notification.php 1 year ago NumberFormatter.php 1 year ago Option.php 1 year ago Period.php 1 year ago Piwik.php 1 year ago Plugin.php 1 year ago Process.php 1 year ago Profiler.php 1 year ago ProxyHeaders.php 2 years ago ProxyHttp.php 1 year ago QuickForm2.php 1 year ago RankingQuery.php 1 year ago ReportRenderer.php 1 year ago Request.php 1 year ago Segment.php 1 year ago Sequence.php 2 years ago Session.php 1 year ago SettingsPiwik.php 1 year ago SettingsServer.php 1 year ago Singleton.php 2 years ago Site.php 1 year ago SiteContentDetector.php 1 year ago SupportedBrowser.php 2 years ago TCPDF.php 1 year ago Theme.php 1 year ago Timer.php 2 years ago Tracker.php 1 year ago Twig.php 1 year ago Unzip.php 1 year ago UpdateCheck.php 1 year ago Updater.php 1 year ago UpdaterErrorException.php 2 years ago Updates.php 1 year ago Url.php 1 year ago UrlHelper.php 1 year ago Version.php 1 year ago View.php 1 year ago bootstrap.php 1 year ago dispatch.php 2 years ago testMinimumPhpVersion.php 2 years ago
Metrics.php
434 lines
1 <?php
2
3 /**
4 * Matomo - free/libre analytics platform
5 *
6 * @link https://matomo.org
7 * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
8 */
9 namespace Piwik;
10
11 use Piwik\Cache as PiwikCache;
12 use Piwik\Columns\Dimension;
13 use Piwik\Tracker\GoalManager;
14 require_once PIWIK_INCLUDE_PATH . "/core/Piwik.php";
15 /**
16 * This class contains metadata regarding core metrics and contains several
17 * related helper functions.
18 *
19 * Of note are the `INDEX_...` constants. In the database, metric column names
20 * in {@link DataTable} rows are stored as integers to save space. The integer
21 * values used are determined by these constants.
22 *
23 * @api
24 */
25 class Metrics
26 {
27 /*
28 * When saving DataTables in the DB, we replace all columns name with these IDs. This saves many bytes,
29 * eg. INDEX_NB_UNIQ_VISITORS is an integer: 4 bytes, but 'nb_uniq_visitors' is 16 bytes at least
30 */
31 public const INDEX_NB_UNIQ_VISITORS = 1;
32 public const INDEX_NB_VISITS = 2;
33 public const INDEX_NB_ACTIONS = 3;
34 public const INDEX_MAX_ACTIONS = 4;
35 public const INDEX_SUM_VISIT_LENGTH = 5;
36 public const INDEX_BOUNCE_COUNT = 6;
37 public const INDEX_NB_VISITS_CONVERTED = 7;
38 public const INDEX_NB_CONVERSIONS = 8;
39 public const INDEX_REVENUE = 9;
40 public const INDEX_GOALS = 10;
41 public const INDEX_SUM_DAILY_NB_UNIQ_VISITORS = 11;
42 // Specific to the Actions reports
43 public const INDEX_PAGE_NB_HITS = 12;
44 public const INDEX_PAGE_SUM_TIME_SPENT = 13;
45 public const INDEX_PAGE_EXIT_NB_UNIQ_VISITORS = 14;
46 public const INDEX_PAGE_EXIT_NB_VISITS = 15;
47 public const INDEX_PAGE_EXIT_SUM_DAILY_NB_UNIQ_VISITORS = 16;
48 public const INDEX_PAGE_ENTRY_NB_UNIQ_VISITORS = 17;
49 public const INDEX_PAGE_ENTRY_SUM_DAILY_NB_UNIQ_VISITORS = 18;
50 public const INDEX_PAGE_ENTRY_NB_VISITS = 19;
51 public const INDEX_PAGE_ENTRY_NB_ACTIONS = 20;
52 public const INDEX_PAGE_ENTRY_SUM_VISIT_LENGTH = 21;
53 public const INDEX_PAGE_ENTRY_BOUNCE_COUNT = 22;
54 // Ecommerce Items reports
55 public const INDEX_ECOMMERCE_ITEM_REVENUE = 23;
56 public const INDEX_ECOMMERCE_ITEM_QUANTITY = 24;
57 public const INDEX_ECOMMERCE_ITEM_PRICE = 25;
58 public const INDEX_ECOMMERCE_ORDERS = 26;
59 public const INDEX_ECOMMERCE_ITEM_PRICE_VIEWED = 27;
60 // Site Search
61 public const INDEX_SITE_SEARCH_HAS_NO_RESULT = 28;
62 public const INDEX_PAGE_IS_FOLLOWING_SITE_SEARCH_NB_HITS = 29;
63 // Performance Analytics
64 public const INDEX_PAGE_SUM_TIME_GENERATION = 30;
65 public const INDEX_PAGE_NB_HITS_WITH_TIME_GENERATION = 31;
66 public const INDEX_PAGE_MIN_TIME_GENERATION = 32;
67 public const INDEX_PAGE_MAX_TIME_GENERATION = 33;
68 // Events
69 public const INDEX_EVENT_NB_HITS = 34;
70 public const INDEX_EVENT_SUM_EVENT_VALUE = 35;
71 public const INDEX_EVENT_MIN_EVENT_VALUE = 36;
72 public const INDEX_EVENT_MAX_EVENT_VALUE = 37;
73 public const INDEX_EVENT_NB_HITS_WITH_VALUE = 38;
74 // Number of unique User IDs
75 public const INDEX_NB_USERS = 39;
76 public const INDEX_SUM_DAILY_NB_USERS = 40;
77 // Contents
78 public const INDEX_CONTENT_NB_IMPRESSIONS = 41;
79 public const INDEX_CONTENT_NB_INTERACTIONS = 42;
80 // Unique visitors fingerprints (useful to process unique visitors across websites)
81 public const INDEX_NB_UNIQ_FINGERPRINTS = 43;
82 // Total number of hits
83 public const INDEX_NB_HITS = 44;
84 // Goal reports
85 public const INDEX_GOAL_NB_CONVERSIONS = 1;
86 public const INDEX_GOAL_REVENUE = 2;
87 public const INDEX_GOAL_NB_VISITS_CONVERTED = 3;
88 public const INDEX_GOAL_ECOMMERCE_REVENUE_SUBTOTAL = 4;
89 public const INDEX_GOAL_ECOMMERCE_REVENUE_TAX = 5;
90 public const INDEX_GOAL_ECOMMERCE_REVENUE_SHIPPING = 6;
91 public const INDEX_GOAL_ECOMMERCE_REVENUE_DISCOUNT = 7;
92 public const INDEX_GOAL_ECOMMERCE_ITEMS = 8;
93 public const INDEX_GOAL_NB_PAGES_UNIQ_BEFORE = 9;
94 public const INDEX_GOAL_NB_CONVERSIONS_ATTRIB = 10;
95 public const INDEX_GOAL_NB_CONVERSIONS_PAGE_RATE = 11;
96 public const INDEX_GOAL_NB_CONVERSIONS_PAGE_UNIQ = 12;
97 public const INDEX_GOAL_NB_CONVERSIONS_ENTRY_RATE = 13;
98 public const INDEX_GOAL_REVENUE_PER_ENTRY = 14;
99 public const INDEX_GOAL_REVENUE_ATTRIB = 15;
100 public const INDEX_GOAL_NB_CONVERSIONS_ENTRY = 16;
101 public const INDEX_GOAL_REVENUE_ENTRY = 17;
102 public static $mappingFromIdToName = array(
103 \Piwik\Metrics::INDEX_NB_UNIQ_VISITORS => 'nb_uniq_visitors',
104 \Piwik\Metrics::INDEX_NB_UNIQ_FINGERPRINTS => 'nb_uniq_fingerprints',
105 \Piwik\Metrics::INDEX_NB_VISITS => 'nb_visits',
106 \Piwik\Metrics::INDEX_NB_ACTIONS => 'nb_actions',
107 \Piwik\Metrics::INDEX_NB_USERS => 'nb_users',
108 \Piwik\Metrics::INDEX_MAX_ACTIONS => 'max_actions',
109 \Piwik\Metrics::INDEX_SUM_VISIT_LENGTH => 'sum_visit_length',
110 \Piwik\Metrics::INDEX_BOUNCE_COUNT => 'bounce_count',
111 \Piwik\Metrics::INDEX_NB_VISITS_CONVERTED => 'nb_visits_converted',
112 \Piwik\Metrics::INDEX_NB_CONVERSIONS => 'nb_conversions',
113 \Piwik\Metrics::INDEX_REVENUE => 'revenue',
114 \Piwik\Metrics::INDEX_GOALS => 'goals',
115 \Piwik\Metrics::INDEX_SUM_DAILY_NB_UNIQ_VISITORS => 'sum_daily_nb_uniq_visitors',
116 \Piwik\Metrics::INDEX_SUM_DAILY_NB_USERS => 'sum_daily_nb_users',
117 \Piwik\Metrics::INDEX_NB_HITS => 'hits',
118 // Actions metrics
119 \Piwik\Metrics::INDEX_PAGE_NB_HITS => 'nb_hits',
120 \Piwik\Metrics::INDEX_PAGE_SUM_TIME_SPENT => 'sum_time_spent',
121 \Piwik\Metrics::INDEX_PAGE_SUM_TIME_GENERATION => 'sum_time_generation',
122 \Piwik\Metrics::INDEX_PAGE_NB_HITS_WITH_TIME_GENERATION => 'nb_hits_with_time_generation',
123 \Piwik\Metrics::INDEX_PAGE_MIN_TIME_GENERATION => 'min_time_generation',
124 \Piwik\Metrics::INDEX_PAGE_MAX_TIME_GENERATION => 'max_time_generation',
125 \Piwik\Metrics::INDEX_PAGE_EXIT_NB_UNIQ_VISITORS => 'exit_nb_uniq_visitors',
126 \Piwik\Metrics::INDEX_PAGE_EXIT_NB_VISITS => 'exit_nb_visits',
127 \Piwik\Metrics::INDEX_PAGE_EXIT_SUM_DAILY_NB_UNIQ_VISITORS => 'sum_daily_exit_nb_uniq_visitors',
128 \Piwik\Metrics::INDEX_PAGE_ENTRY_NB_UNIQ_VISITORS => 'entry_nb_uniq_visitors',
129 \Piwik\Metrics::INDEX_PAGE_ENTRY_SUM_DAILY_NB_UNIQ_VISITORS => 'sum_daily_entry_nb_uniq_visitors',
130 \Piwik\Metrics::INDEX_PAGE_ENTRY_NB_VISITS => 'entry_nb_visits',
131 \Piwik\Metrics::INDEX_PAGE_ENTRY_NB_ACTIONS => 'entry_nb_actions',
132 \Piwik\Metrics::INDEX_PAGE_ENTRY_SUM_VISIT_LENGTH => 'entry_sum_visit_length',
133 \Piwik\Metrics::INDEX_PAGE_ENTRY_BOUNCE_COUNT => 'entry_bounce_count',
134 \Piwik\Metrics::INDEX_PAGE_IS_FOLLOWING_SITE_SEARCH_NB_HITS => 'nb_hits_following_search',
135 // Items reports metrics
136 \Piwik\Metrics::INDEX_ECOMMERCE_ITEM_REVENUE => 'revenue',
137 \Piwik\Metrics::INDEX_ECOMMERCE_ITEM_QUANTITY => 'quantity',
138 \Piwik\Metrics::INDEX_ECOMMERCE_ITEM_PRICE => 'price',
139 \Piwik\Metrics::INDEX_ECOMMERCE_ITEM_PRICE_VIEWED => 'price_viewed',
140 \Piwik\Metrics::INDEX_ECOMMERCE_ORDERS => 'orders',
141 // Events
142 \Piwik\Metrics::INDEX_EVENT_NB_HITS => 'nb_events',
143 \Piwik\Metrics::INDEX_EVENT_SUM_EVENT_VALUE => 'sum_event_value',
144 \Piwik\Metrics::INDEX_EVENT_MIN_EVENT_VALUE => 'min_event_value',
145 \Piwik\Metrics::INDEX_EVENT_MAX_EVENT_VALUE => 'max_event_value',
146 \Piwik\Metrics::INDEX_EVENT_NB_HITS_WITH_VALUE => 'nb_events_with_value',
147 // Contents
148 \Piwik\Metrics::INDEX_CONTENT_NB_IMPRESSIONS => 'nb_impressions',
149 \Piwik\Metrics::INDEX_CONTENT_NB_INTERACTIONS => 'nb_interactions',
150 );
151 public static $mappingFromIdToNameGoal = array(\Piwik\Metrics::INDEX_GOAL_NB_CONVERSIONS => 'nb_conversions', \Piwik\Metrics::INDEX_GOAL_NB_VISITS_CONVERTED => 'nb_visits_converted', \Piwik\Metrics::INDEX_GOAL_REVENUE => 'revenue', \Piwik\Metrics::INDEX_GOAL_ECOMMERCE_REVENUE_SUBTOTAL => 'revenue_subtotal', \Piwik\Metrics::INDEX_GOAL_ECOMMERCE_REVENUE_TAX => 'revenue_tax', \Piwik\Metrics::INDEX_GOAL_ECOMMERCE_REVENUE_SHIPPING => 'revenue_shipping', \Piwik\Metrics::INDEX_GOAL_ECOMMERCE_REVENUE_DISCOUNT => 'revenue_discount', \Piwik\Metrics::INDEX_GOAL_ECOMMERCE_ITEMS => 'items', \Piwik\Metrics::INDEX_GOAL_NB_PAGES_UNIQ_BEFORE => 'nb_conv_pages_before', \Piwik\Metrics::INDEX_GOAL_NB_CONVERSIONS_ATTRIB => 'nb_conversions_attrib', \Piwik\Metrics::INDEX_GOAL_NB_CONVERSIONS_PAGE_RATE => 'nb_conversions_page_rate', \Piwik\Metrics::INDEX_GOAL_NB_CONVERSIONS_PAGE_UNIQ => 'nb_conversions_page_uniq', \Piwik\Metrics::INDEX_GOAL_NB_CONVERSIONS_ENTRY_RATE => 'nb_conversions_entry_rate', \Piwik\Metrics::INDEX_GOAL_REVENUE_PER_ENTRY => 'revenue_per_entry', \Piwik\Metrics::INDEX_GOAL_REVENUE_ATTRIB => 'revenue_attrib', \Piwik\Metrics::INDEX_GOAL_NB_CONVERSIONS_ENTRY => 'nb_conversions_entry', \Piwik\Metrics::INDEX_GOAL_REVENUE_ENTRY => 'revenue_entry');
152 protected static $metricsAggregatedFromLogs = array(\Piwik\Metrics::INDEX_NB_UNIQ_VISITORS, \Piwik\Metrics::INDEX_NB_VISITS, \Piwik\Metrics::INDEX_NB_ACTIONS, \Piwik\Metrics::INDEX_NB_USERS, \Piwik\Metrics::INDEX_MAX_ACTIONS, \Piwik\Metrics::INDEX_SUM_VISIT_LENGTH, \Piwik\Metrics::INDEX_BOUNCE_COUNT, \Piwik\Metrics::INDEX_NB_VISITS_CONVERTED);
153 public static function getMappingFromIdToName()
154 {
155 $cache = PiwikCache::getTransientCache();
156 $cacheKey = \Piwik\CacheId::siteAware(\Piwik\CacheId::pluginAware('Metrics.mappingFromIdToName'));
157 $value = $cache->fetch($cacheKey);
158 if (empty($value)) {
159 $value = self::$mappingFromIdToName;
160 /**
161 * Use this event if your plugin uses custom metric integer IDs to associate those IDs with the
162 * actual metric names (eg, 2 => nb_visits). This allows matomo to automate the replacing
163 * of IDs => metric names for your new metrics.
164 *
165 * **Example**
166 *
167 * public function addMetricIdToNameMapping(&$mapping)
168 * {
169 * $mapping[Archiver::INDEX_MY_NEW_METRIC] = $mapping['MyPlugin_myNewMetric'];
170 * }
171 *
172 * @ignore
173 */
174 \Piwik\Piwik::postEvent('Metrics.addMetricIdToNameMapping', [&$value]);
175 $cache->save($cacheKey, $value);
176 }
177 return $value;
178 }
179 public static function getVisitsMetricNames()
180 {
181 $names = array();
182 foreach (self::$metricsAggregatedFromLogs as $metricId) {
183 $names[$metricId] = self::$mappingFromIdToName[$metricId];
184 }
185 return $names;
186 }
187 public static function getMappingFromNameToId()
188 {
189 static $nameToId = null;
190 if ($nameToId === null) {
191 $nameToId = array_flip(self::$mappingFromIdToName);
192 }
193 return $nameToId;
194 }
195 public static function getMappingFromNameToIdGoal()
196 {
197 static $nameToId = null;
198 if ($nameToId === null) {
199 $nameToId = array_flip(self::$mappingFromIdToNameGoal);
200 }
201 return $nameToId;
202 }
203 /**
204 * Is a lower value for a given column better?
205 * @param $column
206 * @return bool
207 *
208 * @ignore
209 */
210 public static function isLowerValueBetter($column)
211 {
212 $isLowerBetter = null;
213 /**
214 * Use this event to define if a lower value of a metric is better.
215 *
216 * @param string $isLowerBetter should be set to a boolean indicating if lower is better
217 * @param string $column name of the column to determine
218 *
219 * **Example**
220 *
221 * public function checkIsLowerMetricValueBetter(&$isLowerBetter, $metric)
222 * {
223 * if ($metric === 'position') {
224 * $isLowerBetter = true;
225 * }
226 * }
227 */
228 \Piwik\Piwik::postEvent('Metrics.isLowerValueBetter', [&$isLowerBetter, $column]);
229 if (!is_null($isLowerBetter)) {
230 return \true;
231 }
232 $lowerIsBetterPatterns = array('bounce', 'exit');
233 foreach ($lowerIsBetterPatterns as $pattern) {
234 if (strpos($column, $pattern) !== \false) {
235 return \true;
236 }
237 }
238 return \false;
239 }
240 /**
241 * Derive the unit name from a column name
242 * @param $column
243 * @param $idSite
244 * @return string
245 * @ignore
246 */
247 public static function getUnit($column, $idSite)
248 {
249 $nameToUnit = array('_rate' => '%', 'revenue' => \Piwik\Site::getCurrencySymbolFor($idSite), '_time_' => 's');
250 $unit = null;
251 /**
252 * Use this event to define units for custom metrics used in evolution graphs and row evolution only.
253 *
254 * @param string $unit should hold the unit (e.g. %, €, s or empty string)
255 * @param string $column name of the column to determine
256 * @param string $idSite id of the current site
257 */
258 \Piwik\Piwik::postEvent('Metrics.getEvolutionUnit', [&$unit, $column, $idSite]);
259 if (!empty($unit)) {
260 return $unit;
261 }
262 foreach ($nameToUnit as $pattern => $type) {
263 if (strpos($column, $pattern) !== \false) {
264 return $type;
265 }
266 }
267 return '';
268 }
269 public static function getDefaultMetricSemanticTypes() : array
270 {
271 $cacheId = \Piwik\CacheId::pluginAware('DefaultMetricSemanticTypes');
272 $cache = PiwikCache::getTransientCache();
273 $types = $cache->fetch($cacheId);
274 if (empty($types)) {
275 $types = ['nb_visits' => Dimension::TYPE_NUMBER, 'nb_uniq_visitors' => Dimension::TYPE_NUMBER, 'nb_actions' => Dimension::TYPE_NUMBER, 'nb_users' => Dimension::TYPE_NUMBER, 'avg_time_on_page' => Dimension::TYPE_DURATION_S, 'sum_time_spent' => Dimension::TYPE_DURATION_S, 'sum_visit_length' => Dimension::TYPE_DURATION_S, 'bounce_count' => Dimension::TYPE_NUMBER, 'bounce_count_returning' => Dimension::TYPE_NUMBER, 'max_actions' => Dimension::TYPE_NUMBER, 'max_actions_returning' => Dimension::TYPE_NUMBER, 'nb_visits_converted_returning' => Dimension::TYPE_NUMBER, 'sum_visit_length_returning' => Dimension::TYPE_NUMBER, 'nb_visits_converted' => Dimension::TYPE_NUMBER, 'nb_conversions' => Dimension::TYPE_NUMBER, 'revenue' => Dimension::TYPE_MONEY, 'nb_hits' => Dimension::TYPE_NUMBER, 'hits' => Dimension::TYPE_NUMBER, 'entry_nb_visits' => Dimension::TYPE_NUMBER, 'entry_nb_uniq_visitors' => Dimension::TYPE_NUMBER, 'exit_nb_visits' => Dimension::TYPE_NUMBER, 'exit_nb_uniq_visitors' => Dimension::TYPE_NUMBER, 'entry_bounce_count' => Dimension::TYPE_NUMBER, 'exit_bounce_count' => Dimension::TYPE_NUMBER, 'exit_rate' => Dimension::TYPE_PERCENT, 'sum_daily_nb_uniq_visitors' => Dimension::TYPE_NUMBER, 'sum_daily_nb_users' => Dimension::TYPE_NUMBER, 'sum_daily_entry_nb_uniq_visitors' => Dimension::TYPE_NUMBER, 'sum_daily_exit_nb_uniq_visitors' => Dimension::TYPE_NUMBER, 'entry_nb_actions' => Dimension::TYPE_NUMBER, 'entry_sum_visit_length' => Dimension::TYPE_NUMBER, 'nb_actions_per_visit' => Dimension::TYPE_NUMBER, 'avg_time_on_site' => Dimension::TYPE_DURATION_S, 'bounce_rate' => Dimension::TYPE_PERCENT, 'conversion_rate' => Dimension::TYPE_PERCENT];
276 /**
277 * Use this event to notify Matomo of the semantic types of metrics your plugin adds.
278 *
279 * A metric's semantic type is metadata used primarily in integrations with Matomo
280 * and third party services/applications. It provides information that can be used
281 * to determine how to display or use the information.
282 *
283 * It is recommended for your plugin to provide this information so users of third
284 * party services that connect with Matomo can make full use of the data your plugin
285 * tracks.
286 *
287 * See {@link Metrics} for the list of available semantic types.
288 *
289 * @param string $types The array mapping of metric_name => metric semantic type
290 */
291 \Piwik\Piwik::postEvent('Metrics.getDefaultMetricSemanticTypes', [&$types]);
292 $cache->save($cacheId, $types);
293 }
294 return $types;
295 }
296 public static function getDefaultMetricTranslations()
297 {
298 $cacheId = \Piwik\CacheId::pluginAware('DefaultMetricTranslations');
299 $cache = PiwikCache::getTransientCache();
300 if ($cache->contains($cacheId)) {
301 return $cache->fetch($cacheId);
302 }
303 $translations = array('label' => 'General_ColumnLabel', 'date' => 'General_Date', 'avg_time_on_page' => 'General_ColumnAverageTimeOnPage', 'sum_time_spent' => 'General_ColumnSumVisitLength', 'sum_visit_length' => 'General_ColumnSumVisitLength', 'bounce_count' => 'General_ColumnBounces', 'bounce_count_returning' => 'VisitFrequency_ColumnBounceCountForReturningVisits', 'max_actions' => 'General_ColumnMaxActions', 'max_actions_returning' => 'VisitFrequency_ColumnMaxActionsInReturningVisit', 'nb_visits_converted_returning' => 'VisitFrequency_ColumnNbReturningVisitsConverted', 'sum_visit_length_returning' => 'VisitFrequency_ColumnSumVisitLengthReturning', 'nb_visits_converted' => 'General_ColumnVisitsWithConversions', 'nb_conversions' => 'Goals_ColumnConversions', 'revenue' => 'General_ColumnRevenue', 'nb_hits' => 'General_ColumnPageviews', 'hits' => 'General_ColumnHits', 'entry_nb_visits' => 'General_ColumnEntrances', 'entry_nb_uniq_visitors' => 'General_ColumnUniqueEntrances', 'exit_nb_visits' => 'General_ColumnExits', 'exit_nb_uniq_visitors' => 'General_ColumnUniqueExits', 'entry_bounce_count' => 'General_ColumnBounces', 'exit_bounce_count' => 'General_ColumnBounces', 'exit_rate' => 'General_ColumnExitRate');
304 $dailySum = ' (' . \Piwik\Piwik::translate('General_DailySum') . ')';
305 $afterEntry = ' ' . \Piwik\Piwik::translate('General_AfterEntry');
306 $translations['sum_daily_nb_uniq_visitors'] = \Piwik\Piwik::translate('General_ColumnNbUniqVisitors') . $dailySum;
307 $translations['sum_daily_nb_users'] = \Piwik\Piwik::translate('General_ColumnNbUsers') . $dailySum;
308 $translations['sum_daily_entry_nb_uniq_visitors'] = \Piwik\Piwik::translate('General_ColumnUniqueEntrances') . $dailySum;
309 $translations['sum_daily_exit_nb_uniq_visitors'] = \Piwik\Piwik::translate('General_ColumnUniqueExits') . $dailySum;
310 $translations['entry_nb_actions'] = \Piwik\Piwik::translate('General_ColumnNbActions') . $afterEntry;
311 $translations['entry_sum_visit_length'] = \Piwik\Piwik::translate('General_ColumnSumVisitLength') . $afterEntry;
312 $translations = array_merge(self::getDefaultMetrics(), self::getDefaultProcessedMetrics(), $translations);
313 /**
314 * Use this event to register translations for metrics processed by your plugin.
315 *
316 * @param string $translations The array mapping of column_name => Plugin_TranslationForColumn
317 */
318 \Piwik\Piwik::postEvent('Metrics.getDefaultMetricTranslations', array(&$translations));
319 $translations = array_map(array('\\Piwik\\Piwik', 'translate'), $translations);
320 $cache->save($cacheId, $translations);
321 return $translations;
322 }
323 public static function getDefaultMetrics()
324 {
325 $cacheId = \Piwik\CacheId::languageAware('DefaultMetrics');
326 $cache = PiwikCache::getTransientCache();
327 if ($cache->contains($cacheId)) {
328 return $cache->fetch($cacheId);
329 }
330 $translations = array('nb_visits' => 'General_ColumnNbVisits', 'nb_uniq_visitors' => 'General_ColumnNbUniqVisitors', 'nb_actions' => 'General_ColumnNbActions', 'nb_users' => 'General_ColumnNbUsers');
331 $translations = array_map(array('\\Piwik\\Piwik', 'translate'), $translations);
332 $cache->save($cacheId, $translations);
333 return $translations;
334 }
335 public static function getDefaultProcessedMetrics()
336 {
337 $cacheId = \Piwik\CacheId::languageAware('DefaultProcessedMetrics');
338 $cache = PiwikCache::getTransientCache();
339 if ($cache->contains($cacheId)) {
340 return $cache->fetch($cacheId);
341 }
342 $translations = array(
343 // Processed in AddColumnsProcessedMetrics
344 'nb_actions_per_visit' => 'General_ColumnActionsPerVisit',
345 'avg_time_on_site' => 'General_ColumnAvgTimeOnSite',
346 'bounce_rate' => 'General_ColumnBounceRate',
347 'conversion_rate' => 'General_ColumnConversionRate',
348 );
349 $translations = array_map(array('\\Piwik\\Piwik', 'translate'), $translations);
350 $cache->save($cacheId, $translations);
351 return $translations;
352 }
353 public static function getReadableColumnName($columnIdRaw)
354 {
355 $mappingIdToName = self::$mappingFromIdToName;
356 if (array_key_exists($columnIdRaw, $mappingIdToName)) {
357 return $mappingIdToName[$columnIdRaw];
358 }
359 return $columnIdRaw;
360 }
361 public static function getMetricIdsToProcessReportTotal()
362 {
363 return array(self::INDEX_NB_VISITS, self::INDEX_NB_UNIQ_VISITORS, self::INDEX_NB_ACTIONS, self::INDEX_NB_HITS, self::INDEX_PAGE_NB_HITS, self::INDEX_NB_VISITS_CONVERTED, self::INDEX_NB_CONVERSIONS, self::INDEX_BOUNCE_COUNT, self::INDEX_PAGE_ENTRY_BOUNCE_COUNT, self::INDEX_PAGE_ENTRY_NB_VISITS, self::INDEX_PAGE_ENTRY_NB_ACTIONS, self::INDEX_PAGE_EXIT_NB_VISITS, self::INDEX_PAGE_EXIT_NB_UNIQ_VISITORS, self::INDEX_REVENUE);
364 }
365 public static function getDefaultMetricsDocumentation()
366 {
367 $cacheId = \Piwik\CacheId::pluginAware('DefaultMetricsDocumentation');
368 $cache = PiwikCache::getTransientCache();
369 if ($cache->contains($cacheId)) {
370 return $cache->fetch($cacheId);
371 }
372 $translations = array('nb_visits' => 'General_ColumnNbVisitsDocumentation', 'nb_uniq_visitors' => 'General_ColumnNbUniqVisitorsDocumentation', 'nb_actions' => 'General_ColumnNbActionsDocumentation', 'nb_users' => 'General_ColumnNbUsersDocumentation', 'nb_actions_per_visit' => 'General_ColumnActionsPerVisitDocumentation', 'avg_time_on_site' => 'General_ColumnAvgTimeOnSiteDocumentation', 'bounce_rate' => 'General_ColumnBounceRateDocumentation', 'conversion_rate' => 'General_ColumnConversionRateDocumentation', 'avg_time_on_page' => 'General_ColumnAverageTimeOnPageDocumentation', 'nb_hits' => 'General_ColumnPageviewsDocumentation', 'hits' => 'General_ColumnHitsDocumentation', 'exit_rate' => 'General_ColumnExitRateDocumentation');
373 /**
374 * Use this event to register translations for metrics documentation processed by your plugin.
375 *
376 * @param string[] $translations The array mapping of column_name => Plugin_TranslationForColumnDocumentation
377 */
378 \Piwik\Piwik::postEvent('Metrics.getDefaultMetricDocumentationTranslations', array(&$translations));
379 $translations = array_map(array('\\Piwik\\Piwik', 'translate'), $translations);
380 $cache->save($cacheId, $translations);
381 return $translations;
382 }
383 public static function getPercentVisitColumn()
384 {
385 $percentVisitsLabel = str_replace(' ', '&nbsp;', \Piwik\Piwik::translate('General_ColumnPercentageVisits'));
386 return $percentVisitsLabel;
387 }
388 /**
389 * This is a utility method used when building records through log aggregation.
390 *
391 * In records with per-goal conversion metrics the metrics are stored within DataTable Rows
392 * as a column with an array a value. The array is indexed by the goal ID and the column name
393 * is set to `Metrics::INDEX_GOALS`, for example:
394 *
395 * ```
396 * $columns = [
397 * Metrics::INDEX_GOALS = [
398 * $idGoal => [
399 * // ... conversion metrics ...
400 * ],
401 * ],
402 * ];
403 * $row = new Row([DataTable::COLUMNS => $columns]);
404 * ```
405 *
406 * This methods returns an array like `$columns` above based on a goal ID and a row of
407 * metric values for the goal. The result can be added directly to a DataTable record via `sumRowWithLabel()`.
408 *
409 * The goal metrics returned will differ based on whether the goal is user defined or an ecommerce goal.
410 *
411 * @param int $idGoal
412 * @param array $goalsMetrics
413 * @return array
414 */
415 public static function makeGoalColumnsRow(int $idGoal, array $goalsMetrics) : array
416 {
417 if ($idGoal > GoalManager::IDGOAL_ORDER) {
418 // user defined goal
419 $columns = [\Piwik\Metrics::INDEX_GOAL_NB_CONVERSIONS, \Piwik\Metrics::INDEX_GOAL_NB_VISITS_CONVERTED, \Piwik\Metrics::INDEX_GOAL_REVENUE];
420 } elseif ($idGoal == GoalManager::IDGOAL_ORDER) {
421 // ecommerce order
422 $columns = [\Piwik\Metrics::INDEX_GOAL_NB_CONVERSIONS, \Piwik\Metrics::INDEX_GOAL_NB_VISITS_CONVERTED, \Piwik\Metrics::INDEX_GOAL_REVENUE, \Piwik\Metrics::INDEX_GOAL_ECOMMERCE_REVENUE_SUBTOTAL, \Piwik\Metrics::INDEX_GOAL_ECOMMERCE_REVENUE_TAX, \Piwik\Metrics::INDEX_GOAL_ECOMMERCE_REVENUE_SHIPPING, \Piwik\Metrics::INDEX_GOAL_ECOMMERCE_REVENUE_DISCOUNT, \Piwik\Metrics::INDEX_GOAL_ECOMMERCE_ITEMS];
423 } else {
424 // idGoal == GoalManager::IDGOAL_CART (abandoned cart)
425 $columns = [\Piwik\Metrics::INDEX_GOAL_NB_CONVERSIONS, \Piwik\Metrics::INDEX_GOAL_NB_VISITS_CONVERTED, \Piwik\Metrics::INDEX_GOAL_REVENUE, \Piwik\Metrics::INDEX_GOAL_ECOMMERCE_ITEMS];
426 }
427 $values = [];
428 foreach ($columns as $column) {
429 $values[$column] = (float) ($goalsMetrics[$column] ?? 0);
430 }
431 return $values;
432 }
433 }
434