Commit 07eae83a authored by Benjamin Bellamy's avatar Benjamin Bellamy 💬 Committed by Yassine Doghri
Browse files

feat: add map analytics, add episodes analytics, clean analytics page layout, translate countries

parent 196920d6
......@@ -123,10 +123,46 @@ $routes->group(
'as' => 'podcast-delete',
'filter' => 'permission:podcasts-delete',
]);
$routes->get('analytics', 'Podcast::analytics/$1', [
'as' => 'podcast-analytics',
'filter' => 'permission:podcasts-view,podcast-view',
]);
$routes->group('analytics', function ($routes) {
$routes->get('/', 'Podcast::viewAnalytics/$1', [
'as' => 'podcast-analytics',
'filter' => 'permission:podcasts-view,podcast-view',
]);
$routes->get(
'webpages',
'Podcast::viewAnalyticsWebpages/$1',
[
'as' => 'podcast-analytics-webpages',
'filter' => 'permission:podcasts-view,podcast-view',
]
);
$routes->get(
'locations',
'Podcast::viewAnalyticsLocations/$1',
[
'as' => 'podcast-analytics-locations',
'filter' => 'permission:podcasts-view,podcast-view',
]
);
$routes->get(
'unique-listeners',
'Podcast::viewAnalyticsUniqueListeners/$1',
[
'as' => 'podcast-analytics-unique-listeners',
'filter' => 'permission:podcasts-view,podcast-view',
]
);
$routes->get(
'players',
'Podcast::viewAnalyticsPlayers/$1',
[
'as' => 'podcast-analytics-players',
'filter' => 'permission:podcasts-view,podcast-view',
]
);
});
$routes->get(
'analytics-data/(:segment)',
'AnalyticsData::getData/$1/$2',
......
......@@ -58,12 +58,44 @@ class Podcast extends BaseController
return view('admin/podcast/view', $data);
}
public function analytics()
public function viewAnalytics()
{
$data = ['podcast' => $this->podcast];
replace_breadcrumb_params([0 => $this->podcast->title]);
return view('admin/podcast/analytics', $data);
return view('admin/podcast/analytics/index', $data);
}
public function viewAnalyticsWebpages()
{
$data = ['podcast' => $this->podcast];
replace_breadcrumb_params([0 => $this->podcast->title]);
return view('admin/podcast/analytics/webpages', $data);
}
public function viewAnalyticsLocations()
{
$data = ['podcast' => $this->podcast];
replace_breadcrumb_params([0 => $this->podcast->title]);
return view('admin/podcast/analytics/locations', $data);
}
public function viewAnalyticsUniqueListeners()
{
$data = ['podcast' => $this->podcast];
replace_breadcrumb_params([0 => $this->podcast->title]);
return view('admin/podcast/analytics/unique_listeners', $data);
}
public function viewAnalyticsPlayers()
{
$data = ['podcast' => $this->podcast];
replace_breadcrumb_params([0 => $this->podcast->title]);
return view('admin/podcast/analytics/players', $data);
}
public function create()
......
......@@ -20,4 +20,9 @@ class AnalyticsPodcastsByCountry extends Entity
'date' => 'datetime',
'hits' => 'integer',
];
public function getLabels()
{
return lang('Countries.' . $this->attributes['labels']);
}
}
......@@ -23,4 +23,9 @@ class AnalyticsPodcastsByRegion extends Entity
'date' => 'datetime',
'hits' => 'integer',
];
public function getCountryCode()
{
return lang('Countries.' . $this->attributes['country_code']);
}
}
......@@ -20,4 +20,10 @@ class AnalyticsWebsiteByEntryPage extends Entity
'date' => 'datetime',
'hits' => 'integer',
];
public function getLabels()
{
$split = explode('/', $this->attributes['labels']);
return $split[count($split) - 1];
}
}
......@@ -23,4 +23,8 @@ return [
'settings' => 'settings',
'platforms' => 'platforms',
'analytics' => 'Analytics',
'locations' => 'Locations',
'website' => 'Website',
'unique-listeners' => 'Unique listeners',
'players' => 'Players',
];
......@@ -7,14 +7,24 @@
*/
return [
'by_player' => 'Podcast downloads by player (for the past week)',
'by_player_weekly' => 'Podcast downloads by player (for the past week)',
'by_player_yearly' => 'Podcast downloads by player (for the past year)',
'by_device_weekly' => 'Podcast downloads by device (for the past week)',
'by_os_weekly' => 'Podcast downloads by O.S. (for the past week)',
'podcast_by_region' => 'Podcast downloads by region (for the past week)',
'unique_daily_listeners' => 'Daily unique listeners',
'unique_monthly_listeners' => 'Monthly unique listeners',
'by_browser' => 'Website usage by browser (for the past week)',
'by_browser' => 'Web pages usage by browser (for the past week)',
'podcast_by_day' => 'Podcast daily downloads',
'podcast_by_month' => 'Podcast monthly downloads',
'episode_by_day' => 'Episode daily downloads (first 60 days)',
'episode_by_month' => 'Episode monthly downloads',
'episodes_by_day' =>
'5 latest episodes downloads (during their first 60 days)',
'by_country' => 'Podcast downloads by country (for the past week)',
'by_domain' => 'Website visits by origin (for the past week)',
'by_country_weekly' => 'Podcast downloads by country (for the past week)',
'by_country_yearly' => 'Podcast downloads by country (for the past year)',
'by_domain_weekly' => 'Web pages visits by source (for the past week)',
'by_domain_yearly' => 'Web pages visits by source (for the past year)',
'by_entry_page' => 'Web pages visits by landing page (for the past week)',
'podcast_bots' => 'Bots (crawlers)',
];
......@@ -20,5 +20,9 @@ return [
'contributor-add' => 'Add contributor',
'settings' => 'Settings',
'platforms' => 'Podcast platforms',
'podcast-analytics' => 'Audiences Overview',
'podcast-analytics' => 'Audience overview',
'podcast-analytics-webpages' => 'Web pages visits',
'podcast-analytics-locations' => 'Locations',
'podcast-analytics-unique-listeners' => 'Unique listeners',
'podcast-analytics-players' => 'Players',
];
......@@ -20,7 +20,7 @@ return [
'unique_daily_listeners' => 'Auditeurs uniques quotidiens',
'unique_monthly_listeners' => 'Auditeurs uniques mensuels',
'by_browser' =>
'Fréquentation du site par navigateur (sur la dernière semaine)',
'Fréquentation des pages web par navigateur (sur la dernière semaine)',
'podcast_by_day' => 'Téléchargements quotidiens de podcasts',
'podcast_by_month' => 'Téléchargements mensuels de podcasts',
'episode_by_day' =>
......@@ -33,10 +33,10 @@ return [
'by_country_yearly' =>
'Téléchargement de podcasts par pays (sur la dernière année)',
'by_domain_weekly' =>
'Fréquentation du site par origine (sur la dernière semaine)',
'Fréquentation des pages web par origine (sur la dernière semaine)',
'by_domain_yearly' =>
'Fréquentation du site par origine (sur la dernière année)',
'Fréquentation des pages web par origine (sur la dernière année)',
'by_entry_page' =>
'Fréquentation du site par page d’entrée (sur la dernière semaine)',
'Fréquentation des pages web par page d’entrée (sur la dernière semaine)',
'podcast_bots' => 'Robots (bots)',
];
......@@ -20,8 +20,8 @@ return [
'contributor-add' => 'Ajouter un contributeur',
'settings' => 'Paramètres',
'platforms' => 'Plateformes du podcast',
'podcast-analytics' => 'Mesures d’audience',
'podcast-analytics-website' => 'Visites du site web',
'podcast-analytics' => 'Vue d’ensemble',
'podcast-analytics-webpages' => 'Visites des pages web',
'podcast-analytics-locations' => 'Localisations',
'podcast-analytics-unique-listeners' => 'Auditeurs uniques',
'podcast-analytics-players' => 'Lecteurs',
......
......@@ -30,9 +30,14 @@ class AnalyticsPodcastByCountryModel extends Model
*
* @return array
*/
public function getData(int $podcastId): array
public function getDataWeekly(int $podcastId): array
{
if (!($found = cache("{$podcastId}_analytics_podcast_by_country"))) {
$locale = service('request')->getLocale();
if (
!($found = cache(
"{$podcastId}_analytics_podcast_by_country_weekly_{$locale}"
))
) {
$found = $this->select('`country_code` as `labels`')
->selectSum('`hits`', '`values`')
->where([
......@@ -44,7 +49,41 @@ class AnalyticsPodcastByCountryModel extends Model
->findAll(10);
cache()->save(
"{$podcastId}_analytics_podcast_by_country",
"{$podcastId}_analytics_podcast_by_country_weekly_{$locale}",
$found,
600
);
}
return $found;
}
/**
* Gets country data for a podcast
*
* @param int $podcastId
*
* @return array
*/
public function getDataYearly(int $podcastId): array
{
$locale = service('request')->getLocale();
if (
!($found = cache(
"{$podcastId}_analytics_podcast_by_country_yearly_{$locale}"
))
) {
$found = $this->select('`country_code` as `labels`')
->selectSum('`hits`', '`values`')
->where([
'`podcast_id`' => $podcastId,
'`date` >' => date('Y-m-d', strtotime('-1 year')),
])
->groupBy('`labels`')
->orderBy('`values`', 'DESC')
->findAll(10);
cache()->save(
"{$podcastId}_analytics_podcast_by_country_yearly_{$locale}",
$found,
600
);
......
......@@ -37,12 +37,12 @@ class AnalyticsPodcastByEpisodeModel extends Model
))
) {
$lastEpisodes = (new EpisodeModel())
->select('id, season_number, number, title')
->orderBy('id', 'DESC')
->where(['podcast_id' => $podcastId])
->select('`id`, `season_number`, `number`, `title`')
->orderBy('`id`', 'DESC')
->where(['`podcast_id`' => $podcastId])
->findAll(5);
$found = $this->select('age AS X');
$found = $this->select('`age` AS `X`');
$letter = 97;
foreach ($lastEpisodes as $episode) {
......@@ -51,7 +51,7 @@ class AnalyticsPodcastByEpisodeModel extends Model
'(CASE WHEN `episode_id`=' .
$episode->id .
' THEN `hits` END)',
chr($letter) . 'Y'
'`' . chr($letter) . 'Y`'
)
->select(
'"' .
......@@ -62,20 +62,20 @@ class AnalyticsPodcastByEpisodeModel extends Model
? ''
: '-' . $episode->number . '/ ') .
$episode->title .
'" AS ' .
'" AS `' .
chr($letter) .
'Value'
'Value`'
);
$letter++;
}
$found = $found
->where([
'podcast_id' => $podcastId,
'age <' => 60,
'`podcast_id`' => $podcastId,
'`age` <' => 60,
])
->groupBy('X')
->orderBy('X', 'ASC')
->groupBy('`X`')
->orderBy('`X`', 'ASC')
->findAll();
cache()->save(
......@@ -91,14 +91,15 @@ class AnalyticsPodcastByEpisodeModel extends Model
"{$podcastId}_{$episodeId}_analytics_podcast_by_episode_by_day"
))
) {
$found = $this->select('date as labels')
->selectSum('hits', 'values')
$found = $this->select('`date as `labels`')
->selectSum('`hits`', '`values`')
->where([
'episode_id' => $episodeId,
'podcast_id' => $podcastId,
'`episode_id`' => $episodeId,
'`podcast_id`' => $podcastId,
'`age` <' => 60,
])
->groupBy('labels')
->orderBy('labels', 'ASC')
->groupBy('`labels`')
->orderBy('`labels`', 'ASC')
->findAll();
cache()->save(
......@@ -110,4 +111,35 @@ class AnalyticsPodcastByEpisodeModel extends Model
return $found;
}
}
/**
* @param int $podcastId, $episodeId
*
* @return array
*/
public function getDataByMonth(int $podcastId, int $episodeId = null): array
{
if (
!($found = cache(
"{$podcastId}_{$episodeId}_analytics_podcast_by_episode_by_month"
))
) {
$found = $this->select('DATE_FORMAT(`date`,"%Y-%m-01") as `labels`')
->selectSum('`hits`', '`values`')
->where([
'episode_id' => $episodeId,
'podcast_id' => $podcastId,
])
->groupBy('`labels`')
->orderBy('`labels`', 'ASC')
->findAll();
cache()->save(
"{$podcastId}_{$episodeId}_analytics_podcast_by_episode_by_month",
$found,
600
);
}
return $found;
}
}
......@@ -30,11 +30,11 @@ class AnalyticsPodcastByPlayerModel extends Model
*
* @return array
*/
public function getDataByApp(int $podcastId): array
public function getDataByAppWeekly(int $podcastId): array
{
if (
!($found = cache(
"{$podcastId}_analytics_podcasts_by_player_by_app"
"{$podcastId}_analytics_podcasts_by_player_by_app_weekly"
))
) {
$found = $this->select('`app` as `labels`')
......@@ -50,92 +50,148 @@ class AnalyticsPodcastByPlayerModel extends Model
->findAll(10);
cache()->save(
"{$podcastId}_analytics_podcasts_by_player_by_app",
"{$podcastId}_analytics_podcasts_by_player_by_app_weekly",
$found,
600
);
}
return $found;
}
/**
* Gets device data for a podcast
* Gets player data for a podcast
*
* @param int $podcastId
*
* @return array
*/
public function getDataByDevice(int $podcastId): array
public function getDataByAppYearly(int $podcastId): array
{
if (
!($found = cache(
"{$podcastId}_analytics_podcasts_by_player_by_device"
"{$podcastId}_analytics_podcasts_by_player_by_app_yearly"
))
) {
$foundApp = $this->select(
'CONCAT_WS("/", `device`, `os`, `app`) as `ids`, `app` as `labels`, CONCAT_WS("/", `device`, `os`) as `parents`'
)
$found = $this->select('`app` as `labels`')
->selectSum('`hits`', '`values`')
->where([
'`podcast_id`' => $podcastId,
'`app` !=' => null,
'`app` !=' => '',
'`bot`' => 0,
'`date` >' => date('Y-m-d', strtotime('-1 week')),
'`date` >' => date('Y-m-d', strtotime('-1 year')),
])
->groupBy('`ids`')
->groupBy('`labels`')
->orderBy('`values`', 'DESC')
->findAll();
->findAll(10);
$foundOs = $this->select(
'CONCAT_WS("/", `device`, `os`) as `ids`, `os` as `labels`, `device` as `parents`'
)
cache()->save(
"{$podcastId}_analytics_podcasts_by_player_by_app_yearly",
$found,
600
);
}
return $found;
}
/**
* Gets os data for a podcast
*
* @param int $podcastId
*
* @return array
*/
public function getDataByOsWeekly(int $podcastId): array
{
if (
!($found = cache(
"{$podcastId}_analytics_podcasts_by_player_by_os_weekly"
))
) {
$found = $this->select('`os` as `labels`')
->selectSum('`hits`', '`values`')
->where([
'`podcast_id`' => $podcastId,
'`os` !=' => null,
'`app` !=' => '',
'`bot`' => 0,
'`date` >' => date('Y-m-d', strtotime('-1 week')),
])
->groupBy('`ids`')
->groupBy('`labels`')
->orderBy('`values`', 'DESC')
->findAll();
->findAll(10);
cache()->save(
"{$podcastId}_analytics_podcasts_by_player_by_os_weekly",
$found,
600
);
}
return $found;
}
$foundDevice = $this->select(
'`device` as `ids`, `device` as `labels`, "" as `parents`'
)
/**
* Gets player data for a podcast
*
* @param int $podcastId
*
* @return array
*/
public function getDataByDeviceWeekly(int $podcastId): array
{
if (
!($found = cache(
"{$podcastId}_analytics_podcasts_by_player_by_device_weekly"
))
) {
$found = $this->select('`device` as `labels`')
->selectSum('`hits`', '`values`')
->where([
'`podcast_id`' => $podcastId,
'`device` !=' => null,
'`device` !=' => '',
'`bot`' => 0,
'`date` >' => date('Y-m-d', strtotime('-1 week')),
])
->groupBy('`ids`')
->groupBy('`labels`')
->orderBy('`values`', 'DESC')
->findAll();
->findAll(10);
cache()->save(
"{$podcastId}_analytics_podcasts_by_player_by_device_weekly",
$found,
600
);
}
return $found;
}
$foundBot = $this->select(
'"bots" as `ids`, "Bots" as `labels`, "" as `parents`'
)
/**
* Gets bots data for a podcast
*
* @param int $podcastId
*
* @return array
*/
public function getDataBots(int $podcastId): array
{
if (
!($found = cache("{$podcastId}_analytics_podcasts_by_player_bots"))
) {
$found = $this->select('DATE_FORMAT(`date`,"%Y-%m-01") as `labels`')
->selectSum('`hits`', '`values`')
->where([
'`podcast_id`' => $podcastId,
'`bot`' => 1,
'`date` >' => date('Y-m-d', strtotime('-1 week')),
'`date` >' => date('Y-m-d', strtotime('-1 year')),
])
->groupBy('`ids`')
->orderBy('`values`', 'DESC')
->findAll();
->groupBy('`labels`')
->orderBy('`labels`', 'ASC')
->findAll(10);
$found = array_merge($foundApp, $foundOs, $foundDevice, $foundBot);
cache()->save(
"{$podcastId}_analytics_podcasts_by_player_by_device",
"{$podcastId}_analytics_podcasts_by_player_bots",
$found,
600
);
}
return $found;
}
}
......@@ -32,11 +32,16 @@ class AnalyticsPodcastByRegionModel extends Model
*/
public function getData(int $podcastId): array
{
if (!($found = cache("{$podcastId}_analytics_podcast_by_region"))) {
$locale = service('request')->getLocale();
if (
!($found = cache(
"{$podcastId}_analytics_podcast_by_region_{$locale}"
))
) {
$found = $this->select(
'`country_code`, `region_code`, `latitude`, `longitude`'
)
->selectSum('`hits`', '`values`')
->selectSum('`hits`', '`value`')
->groupBy(
'`country_code`, `region_code`, `latitude`, `longitude`'