diff --git a/app/Config/Routes.php b/app/Config/Routes.php
index 9e1209c07c325c017bc88e4c2b92f9f821b23220..ce41ca17a82a98bb3f2978e474c4c8a8af44bbf5 100644
--- a/app/Config/Routes.php
+++ b/app/Config/Routes.php
@@ -59,10 +59,10 @@ $routes->group(config('App')->installGateway, function ($routes) {
     ]);
 });
 
-// Route for podcast audio file analytics (/audio/podcast_id/episode_id/bytes_threshold/filesize/podcast_folder/filename.mp3)
+// Route for podcast audio file analytics (/audio/podcast_id/episode_id/bytes_threshold/filesize/duration/podcast_folder/filename.mp3)
 $routes->add(
-    'audio/(:num)/(:num)/(:num)/(:num)/(:any)',
-    'Analytics::hit/$1/$2/$3/$4/$5',
+    'audio/(:num)/(:num)/(:num)/(:num)/(:num)/(:any)',
+    'Analytics::hit/$1/$2/$3/$4/$5/$6',
     [
         'as' => 'analytics_hit',
     ]
diff --git a/app/Controllers/Admin/Episode.php b/app/Controllers/Admin/Episode.php
index 82a73a14c20726e3f517350e8ce345d22777a9f4..6dc61de177b18870f31b6ea986dea16f8292d83a 100644
--- a/app/Controllers/Admin/Episode.php
+++ b/app/Controllers/Admin/Episode.php
@@ -112,7 +112,7 @@ class Episode extends BaseController
             'slug' => $this->request->getPost('slug'),
             'guid' => '',
             'enclosure' => $this->request->getFile('enclosure'),
-            'description' => $this->request->getPost('description'),
+            'description_markdown' => $this->request->getPost('description'),
             'image' => $this->request->getFile('image'),
             'parental_advisory' =>
                 $this->request->getPost('parental_advisory') !== 'undefined'
@@ -121,7 +121,7 @@ class Episode extends BaseController
             'number' => $this->request->getPost('episode_number'),
             'season_number' => $this->request->getPost('season_number'),
             'type' => $this->request->getPost('type'),
-            'block' => $this->request->getPost('block') == 'yes',
+            'is_blocked' => $this->request->getPost('block') == 'yes',
             'created_by' => user(),
             'updated_by' => user(),
             'published_at' => Time::createFromFormat(
@@ -140,11 +140,11 @@ class Episode extends BaseController
                 ->with('errors', $episodeModel->errors());
         }
 
-        // update podcast's episode_description_footer if changed
+        // update podcast's episode_description_footer_markdown if changed
         $podcastModel = new PodcastModel();
 
-        if ($this->podcast->hasChanged('episode_description_footer')) {
-            $this->podcast->episode_description_footer = $this->request->getPost(
+        if ($this->podcast->hasChanged('episode_description_footer_markdown')) {
+            $this->podcast->episode_description_footer_markdown = $this->request->getPost(
                 'description_footer'
             );
 
@@ -197,7 +197,9 @@ class Episode extends BaseController
 
         $this->episode->title = $this->request->getPost('title');
         $this->episode->slug = $this->request->getPost('slug');
-        $this->episode->description = $this->request->getPost('description');
+        $this->episode->description_markdown = $this->request->getPost(
+            'description'
+        );
         $this->episode->parental_advisory =
             $this->request->getPost('parental_advisory') !== 'undefined'
                 ? $this->request->getPost('parental_advisory')
@@ -207,7 +209,7 @@ class Episode extends BaseController
             ? $this->request->getPost('season_number')
             : null;
         $this->episode->type = $this->request->getPost('type');
-        $this->episode->block = $this->request->getPost('block') == 'yes';
+        $this->episode->is_blocked = $this->request->getPost('block') == 'yes';
         $this->episode->published_at = Time::createFromFormat(
             'Y-m-d H:i',
             $this->request->getPost('publication_date'),
@@ -233,12 +235,12 @@ class Episode extends BaseController
                 ->with('errors', $episodeModel->errors());
         }
 
-        // update podcast's episode_description_footer if changed
-        $this->podcast->episode_description_footer = $this->request->getPost(
+        // update podcast's episode_description_footer_markdown if changed
+        $this->podcast->episode_description_footer_markdown = $this->request->getPost(
             'description_footer'
         );
 
-        if ($this->podcast->hasChanged('episode_description_footer')) {
+        if ($this->podcast->hasChanged('episode_description_footer_markdown')) {
             $podcastModel = new PodcastModel();
             if (!$podcastModel->update($this->podcast->id, $this->podcast)) {
                 return redirect()
diff --git a/app/Controllers/Admin/Podcast.php b/app/Controllers/Admin/Podcast.php
index 542f4f921e474000c1335d1d7bcb08893c36935d..c46ed1e8a56c158cd44f372667991636c08a1fb7 100644
--- a/app/Controllers/Admin/Podcast.php
+++ b/app/Controllers/Admin/Podcast.php
@@ -95,7 +95,7 @@ class Podcast extends BaseController
         $data = ['podcast' => $this->podcast];
 
         replace_breadcrumb_params([0 => $this->podcast->title]);
-        return view('admin/podcast/analytics/listening-time', $data);
+        return view('admin/podcast/analytics/listening_time', $data);
     }
 
     public function viewAnalyticsPlayers()
@@ -141,9 +141,9 @@ class Podcast extends BaseController
         $podcast = new \App\Entities\Podcast([
             'title' => $this->request->getPost('title'),
             'name' => $this->request->getPost('name'),
-            'description' => $this->request->getPost('description'),
+            'description_markdown' => $this->request->getPost('description'),
             'image' => $this->request->getFile('image'),
-            'language' => $this->request->getPost('language'),
+            'language_code' => $this->request->getPost('language'),
             'category_id' => $this->request->getPost('category'),
             'parental_advisory' =>
                 $this->request->getPost('parental_advisory') !== 'undefined'
@@ -154,9 +154,9 @@ class Podcast extends BaseController
             'publisher' => $this->request->getPost('publisher'),
             'type' => $this->request->getPost('type'),
             'copyright' => $this->request->getPost('copyright'),
-            'block' => $this->request->getPost('block') === 'yes',
-            'complete' => $this->request->getPost('complete') === 'yes',
-            'lock' => $this->request->getPost('lock') === 'yes',
+            'is_blocked' => $this->request->getPost('is_blocked') === 'yes',
+            'is_completed' => $this->request->getPost('complete') === 'yes',
+            'is_locked' => $this->request->getPost('lock') === 'yes',
             'created_by' => user(),
             'updated_by' => user(),
         ]);
@@ -259,6 +259,10 @@ class Podcast extends BaseController
                 ->with('errors', [lang('PodcastImport.lock_import')]);
         }
 
+        $converter = new HtmlConverter();
+
+        $channelDescriptionHtml = $feed->channel[0]->description;
+
         $podcast = new \App\Entities\Podcast([
             'name' => $this->request->getPost('name'),
             'imported_feed_url' => $this->request->getPost('imported_feed_url'),
@@ -266,9 +270,12 @@ class Podcast extends BaseController
                 route_to('podcast_feed', $this->request->getPost('name'))
             ),
             'title' => $feed->channel[0]->title,
-            'description' => $feed->channel[0]->description,
+            'description_markdown' => $converter->convert(
+                $channelDescriptionHtml
+            ),
+            'description_html' => $channelDescriptionHtml,
             'image' => download_file($nsItunes->image->attributes()),
-            'language' => $this->request->getPost('language'),
+            'language_code' => $this->request->getPost('language'),
             'category_id' => $this->request->getPost('category'),
             'parental_advisory' => empty($nsItunes->explicit)
                 ? null
@@ -282,10 +289,10 @@ class Podcast extends BaseController
             'publisher' => $nsItunes->author,
             'type' => empty($nsItunes->type) ? 'episodic' : $nsItunes->type,
             'copyright' => $feed->channel[0]->copyright,
-            'block' => empty($nsItunes->block)
+            'is_blocked' => empty($nsItunes->block)
                 ? false
                 : $nsItunes->block === 'yes',
-            'complete' => empty($nsItunes->complete)
+            'is_completed' => empty($nsItunes->complete)
                 ? false
                 : $nsItunes->complete === 'yes',
             'created_by' => user(),
@@ -314,8 +321,6 @@ class Podcast extends BaseController
             $podcastAdminGroup->id
         );
 
-        $converter = new HtmlConverter();
-
         $numberItems = $feed->channel[0]->item->count();
         $lastItem =
             !empty($this->request->getPost('max_episodes')) &&
@@ -347,20 +352,24 @@ class Podcast extends BaseController
             }
             $slugs[] = $slug;
 
+            $itemDescriptionHtml =
+                $this->request->getPost('description_field') === 'summary'
+                    ? $nsItunes->summary
+                    : ($this->request->getPost('description_field') ===
+                    'subtitle_summary'
+                        ? $nsItunes->subtitle . '<br/>' . $nsItunes->summary
+                        : $item->description);
+
             $newEpisode = new \App\Entities\Episode([
                 'podcast_id' => $newPodcastId,
                 'guid' => empty($item->guid) ? null : $item->guid,
                 'title' => $item->title,
                 'slug' => $slug,
                 'enclosure' => download_file($item->enclosure->attributes()),
-                'description' => $converter->convert(
-                    $this->request->getPost('description_field') === 'summary'
-                        ? $nsItunes->summary
-                        : ($this->request->getPost('description_field') ===
-                        'subtitle_summary'
-                            ? $nsItunes->subtitle . "\n" . $nsItunes->summary
-                            : $item->description)
+                'description_markdown' => $converter->convert(
+                    $itemDescriptionHtml
                 ),
+                'description_html' => $itemDescriptionHtml,
                 'image' =>
                     !$nsItunes->image || empty($nsItunes->image->attributes())
                         ? null
@@ -379,12 +388,14 @@ class Podcast extends BaseController
                 'season_number' => empty(
                     $this->request->getPost('season_number')
                 )
-                    ? $nsItunes->season
+                    ? (!empty($nsItunes->season)
+                        ? $nsItunes->season
+                        : null)
                     : $this->request->getPost('season_number'),
                 'type' => empty($nsItunes->episodeType)
                     ? 'full'
                     : $nsItunes->episodeType,
-                'block' => empty($nsItunes->block)
+                'is_blocked' => empty($nsItunes->block)
                     ? false
                     : $nsItunes->block === 'yes',
                 'created_by' => user(),
@@ -441,13 +452,15 @@ class Podcast extends BaseController
 
         $this->podcast->title = $this->request->getPost('title');
         $this->podcast->name = $this->request->getPost('name');
-        $this->podcast->description = $this->request->getPost('description');
+        $this->podcast->description_markdown = $this->request->getPost(
+            'description'
+        );
 
         $image = $this->request->getFile('image');
         if ($image->isValid()) {
             $this->podcast->image = $image;
         }
-        $this->podcast->language = $this->request->getPost('language');
+        $this->podcast->language_code = $this->request->getPost('language');
         $this->podcast->category_id = $this->request->getPost('category');
         $this->podcast->parental_advisory =
             $this->request->getPost('parental_advisory') !== 'undefined'
@@ -458,10 +471,11 @@ class Podcast extends BaseController
         $this->podcast->owner_email = $this->request->getPost('owner_email');
         $this->podcast->type = $this->request->getPost('type');
         $this->podcast->copyright = $this->request->getPost('copyright');
-        $this->podcast->block = $this->request->getPost('block') === 'yes';
-        $this->podcast->complete =
+        $this->podcast->is_blocked =
+            $this->request->getPost('is_blocked') === 'yes';
+        $this->podcast->is_completed =
             $this->request->getPost('complete') === 'yes';
-        $this->podcast->lock = $this->request->getPost('lock') === 'yes';
+        $this->podcast->is_lock = $this->request->getPost('lock') === 'yes';
         $this->updated_by = user();
 
         $db = \Config\Database::connect();
diff --git a/app/Controllers/Admin/PodcastSettings.php b/app/Controllers/Admin/PodcastSettings.php
index e9c079c92ae372cd1d15caea0f5942b0b4477e90..9beabef1334678d8303d0eb62b67e3d1937bf5dd 100644
--- a/app/Controllers/Admin/PodcastSettings.php
+++ b/app/Controllers/Admin/PodcastSettings.php
@@ -71,14 +71,14 @@ class PodcastSettings extends BaseController
                     'platform_id' => $platformId,
                     'podcast_id' => $this->podcast->id,
                     'link_url' => $platformLinkUrl,
-                    'visible' => array_key_exists('visible', $platformLink)
+                    'is_visible' => array_key_exists('visible', $platformLink)
                         ? $platformLink['visible'] == 'yes'
                         : false,
                 ]);
             }
         }
 
-        $platformModel->savePlatformLinks(
+        $platformModel->savePodcastPlatforms(
             $this->podcast->id,
             $platformLinksData
         );
diff --git a/app/Controllers/Analytics.php b/app/Controllers/Analytics.php
index e0cf865c57b012d815c466e29e91810b0b4f2a6a..7db0bee0151b958210e833dceea5e348819bb290 100644
--- a/app/Controllers/Analytics.php
+++ b/app/Controllers/Analytics.php
@@ -51,6 +51,7 @@ class Analytics extends Controller
         $episodeId,
         $bytesThreshold,
         $fileSize,
+        $duration,
         ...$filename
     ) {
         helper('media');
@@ -62,6 +63,7 @@ class Analytics extends Controller
             $episodeId,
             $bytesThreshold,
             $fileSize,
+            $duration,
             $serviceName
         );
         return redirect()->to(media_base_url($filename));
diff --git a/app/Database/Migrations/2020-05-29-152000_add_categories.php b/app/Database/Migrations/2020-05-29-152000_add_categories.php
index 576a8daaf977f02aac09aecfe5f90466eb04f05c..2fa255a3a523fb5a8d49f13fd20c0abb78cd7ad0 100644
--- a/app/Database/Migrations/2020-05-29-152000_add_categories.php
+++ b/app/Database/Migrations/2020-05-29-152000_add_categories.php
@@ -20,25 +20,23 @@ class AddCategories extends Migration
         $this->forge->addField([
             'id' => [
                 'type' => 'INT',
-                'constraint' => 10,
                 'unsigned' => true,
             ],
             'parent_id' => [
                 'type' => 'INT',
-                'constraint' => 10,
                 'unsigned' => true,
             ],
             'code' => [
                 'type' => 'VARCHAR',
-                'constraint' => 191,
+                'constraint' => 32,
             ],
             'apple_category' => [
                 'type' => 'VARCHAR',
-                'constraint' => 1024,
+                'constraint' => 32,
             ],
             'google_category' => [
                 'type' => 'VARCHAR',
-                'constraint' => 1024,
+                'constraint' => 32,
             ],
         ]);
         $this->forge->addKey('id', true);
diff --git a/app/Database/Migrations/2020-05-30-101000_add_languages.php b/app/Database/Migrations/2020-05-30-101000_add_languages.php
index ae11bdf705e7c317854728336cfda6303056b8a6..cc58df49f85dcdef4679c0eb989ab8303b3eb590 100644
--- a/app/Database/Migrations/2020-05-30-101000_add_languages.php
+++ b/app/Database/Migrations/2020-05-30-101000_add_languages.php
@@ -20,17 +20,12 @@ class AddLanguages extends Migration
         $this->forge->addField([
             'code' => [
                 'type' => 'VARCHAR',
-                'comment' => 'ISO 639-1 language code.',
+                'comment' => 'ISO 639-1 language code',
                 'constraint' => 2,
             ],
-            'name' => [
-                'type' => 'VARCHAR',
-                'comment' => 'English language name.',
-                'constraint' => 191,
-            ],
             'native_name' => [
                 'type' => 'VARCHAR',
-                'constraint' => 191,
+                'constraint' => 128,
             ],
         ]);
         $this->forge->addKey('code', true);
diff --git a/app/Database/Migrations/2020-05-30-101500_add_podcasts.php b/app/Database/Migrations/2020-05-30-101500_add_podcasts.php
index 96633865eef03a16e3c044aab1583ef25a5ea0c8..3ba966f8d378fc19b3b74252c53422a4d1a0b28e 100644
--- a/app/Database/Migrations/2020-05-30-101500_add_podcasts.php
+++ b/app/Database/Migrations/2020-05-30-101500_add_podcasts.php
@@ -19,34 +19,35 @@ class AddPodcasts extends Migration
     {
         $this->forge->addField([
             'id' => [
-                'type' => 'BIGINT',
-                'constraint' => 20,
+                'type' => 'INT',
                 'unsigned' => true,
                 'auto_increment' => true,
             ],
             'title' => [
                 'type' => 'VARCHAR',
-                'constraint' => 1024,
+                'constraint' => 128,
             ],
             'name' => [
                 'type' => 'VARCHAR',
-                'constraint' => 191,
+                'constraint' => 32,
                 'unique' => true,
             ],
-            'description' => [
+            'description_markdown' => [
+                'type' => 'TEXT',
+            ],
+            'description_html' => [
                 'type' => 'TEXT',
             ],
             'image_uri' => [
                 'type' => 'VARCHAR',
-                'constraint' => 1024,
+                'constraint' => 255,
             ],
-            'language' => [
+            'language_code' => [
                 'type' => 'VARCHAR',
                 'constraint' => 2,
             ],
             'category_id' => [
                 'type' => 'INT',
-                'constraint' => 10,
                 'unsigned' => true,
                 'default' => 0,
             ],
@@ -58,15 +59,15 @@ class AddPodcasts extends Migration
             ],
             'owner_name' => [
                 'type' => 'VARCHAR',
-                'constraint' => 1024,
+                'constraint' => 128,
             ],
             'owner_email' => [
                 'type' => 'VARCHAR',
-                'constraint' => 1024,
+                'constraint' => 255,
             ],
             'publisher' => [
                 'type' => 'VARCHAR',
-                'constraint' => 1024,
+                'constraint' => 128,
                 'null' => true,
             ],
             'type' => [
@@ -76,67 +77,69 @@ class AddPodcasts extends Migration
             ],
             'copyright' => [
                 'type' => 'VARCHAR',
-                'constraint' => 1024,
+                'constraint' => 128,
+                'null' => true,
+            ],
+            'episode_description_footer_markdown' => [
+                'type' => 'TEXT',
                 'null' => true,
             ],
-            'episode_description_footer' => [
+            'episode_description_footer_html' => [
                 'type' => 'TEXT',
                 'null' => true,
             ],
-            'block' => [
+            'is_blocked' => [
                 'type' => 'TINYINT',
                 'constraint' => 1,
                 'default' => 0,
             ],
-            'complete' => [
+            'is_completed' => [
                 'type' => 'TINYINT',
                 'constraint' => 1,
                 'default' => 0,
             ],
-            'lock' => [
+            'is_locked' => [
                 'type' => 'TINYINT',
                 'constraint' => 1,
-                'comment' =>
-                    'This tells other podcast platforms whether they are allowed to import this feed.',
                 'default' => 1,
             ],
             'imported_feed_url' => [
                 'type' => 'VARCHAR',
-                'constraint' => 1024,
+                'constraint' => 512,
                 'comment' =>
                     'The RSS feed URL if this podcast was imported, NULL otherwise.',
                 'null' => true,
             ],
             'new_feed_url' => [
                 'type' => 'VARCHAR',
-                'constraint' => 1024,
+                'constraint' => 512,
                 'comment' =>
                     'The RSS new feed URL if this podcast is moving out, NULL otherwise.',
                 'null' => true,
             ],
             'created_by' => [
                 'type' => 'INT',
-                'constraint' => 11,
                 'unsigned' => true,
             ],
             'updated_by' => [
                 'type' => 'INT',
-                'constraint' => 11,
                 'unsigned' => true,
             ],
             'created_at' => [
-                'type' => 'TIMESTAMP',
+                'type' => 'DATETIME',
             ],
             'updated_at' => [
-                'type' => 'TIMESTAMP',
+                'type' => 'DATETIME',
             ],
             'deleted_at' => [
                 'type' => 'DATETIME',
                 'null' => true,
             ],
         ]);
+
         $this->forge->addKey('id', true);
         $this->forge->addForeignKey('category_id', 'categories', 'id');
+        $this->forge->addForeignKey('language_code', 'languages', 'code');
         $this->forge->addForeignKey('created_by', 'users', 'id');
         $this->forge->addForeignKey('updated_by', 'users', 'id');
         $this->forge->createTable('podcasts');
diff --git a/app/Database/Migrations/2020-06-05-170000_add_episodes.php b/app/Database/Migrations/2020-06-05-170000_add_episodes.php
index 313346866b8c377c2004c18ed95f3621387afe6a..a4a2011a6a95948de1c7908108581f4f0ddfeb8a 100644
--- a/app/Database/Migrations/2020-06-05-170000_add_episodes.php
+++ b/app/Database/Migrations/2020-06-05-170000_add_episodes.php
@@ -19,23 +19,21 @@ class AddEpisodes extends Migration
     {
         $this->forge->addField([
             'id' => [
-                'type' => 'BIGINT',
-                'constraint' => 20,
+                'type' => 'INT',
                 'unsigned' => true,
                 'auto_increment' => true,
             ],
             'podcast_id' => [
-                'type' => 'BIGINT',
-                'constraint' => 20,
+                'type' => 'INT',
                 'unsigned' => true,
             ],
             'guid' => [
                 'type' => 'VARCHAR',
-                'constraint' => 191,
+                'constraint' => 255,
             ],
             'title' => [
                 'type' => 'VARCHAR',
-                'constraint' => 1024,
+                'constraint' => 128,
             ],
             'slug' => [
                 'type' => 'VARCHAR',
@@ -43,11 +41,10 @@ class AddEpisodes extends Migration
             ],
             'enclosure_uri' => [
                 'type' => 'VARCHAR',
-                'constraint' => 1024,
+                'constraint' => 255,
             ],
             'enclosure_duration' => [
                 'type' => 'INT',
-                'constraint' => 10,
                 'unsigned' => true,
                 'comment' => 'Playtime in seconds',
             ],
@@ -57,23 +54,25 @@ class AddEpisodes extends Migration
             ],
             'enclosure_filesize' => [
                 'type' => 'INT',
-                'constraint' => 10,
                 'unsigned' => true,
                 'comment' => 'File size in bytes',
             ],
             'enclosure_headersize' => [
                 'type' => 'INT',
-                'constraint' => 10,
                 'unsigned' => true,
                 'comment' => 'Header size in bytes',
             ],
-            'description' => [
+            'description_markdown' => [
+                'type' => 'TEXT',
+                'null' => true,
+            ],
+            'description_html' => [
                 'type' => 'TEXT',
                 'null' => true,
             ],
             'image_uri' => [
                 'type' => 'VARCHAR',
-                'constraint' => 1024,
+                'constraint' => 255,
                 'null' => true,
             ],
             'parental_advisory' => [
@@ -84,13 +83,11 @@ class AddEpisodes extends Migration
             ],
             'number' => [
                 'type' => 'INT',
-                'constraint' => 10,
                 'unsigned' => true,
                 'null' => true,
             ],
             'season_number' => [
                 'type' => 'INT',
-                'constraint' => 10,
                 'unsigned' => true,
                 'null' => true,
             ],
@@ -99,19 +96,17 @@ class AddEpisodes extends Migration
                 'constraint' => ['trailer', 'full', 'bonus'],
                 'default' => 'full',
             ],
-            'block' => [
+            'is_blocked' => [
                 'type' => 'TINYINT',
                 'constraint' => 1,
                 'default' => 0,
             ],
             'created_by' => [
                 'type' => 'INT',
-                'constraint' => 11,
                 'unsigned' => true,
             ],
             'updated_by' => [
                 'type' => 'INT',
-                'constraint' => 11,
                 'unsigned' => true,
             ],
             'published_at' => [
@@ -119,10 +114,10 @@ class AddEpisodes extends Migration
                 'null' => true,
             ],
             'created_at' => [
-                'type' => 'TIMESTAMP',
+                'type' => 'DATETIME',
             ],
             'updated_at' => [
-                'type' => 'TIMESTAMP',
+                'type' => 'DATETIME',
             ],
             'deleted_at' => [
                 'type' => 'DATETIME',
diff --git a/app/Database/Migrations/2020-06-05-190000_add_platforms.php b/app/Database/Migrations/2020-06-05-190000_add_platforms.php
index d24750f4b5f83bdc7c743173ad1068746a86fff1..6fbcc0327a060a039a109adc4993055a183c0552 100644
--- a/app/Database/Migrations/2020-06-05-190000_add_platforms.php
+++ b/app/Database/Migrations/2020-06-05-190000_add_platforms.php
@@ -19,39 +19,34 @@ class AddPlatforms extends Migration
     {
         $this->forge->addField([
             'id' => [
-                'type' => 'BIGINT',
-                'constraint' => 20,
+                'type' => 'INT',
                 'unsigned' => true,
                 'auto_increment' => true,
             ],
             'name' => [
                 'type' => 'VARCHAR',
-                'constraint' => 191,
+                'constraint' => 32,
                 'unique' => true,
             ],
             'label' => [
                 'type' => 'VARCHAR',
-                'constraint' => 191,
+                'constraint' => 32,
             ],
             'home_url' => [
                 'type' => 'VARCHAR',
-                'constraint' => 191,
+                'constraint' => 255,
             ],
             'submit_url' => [
                 'type' => 'VARCHAR',
-                'constraint' => 191,
+                'constraint' => 512,
                 'null' => true,
                 'default' => null,
             ],
-            'icon_filename' => [
-                'type' => 'VARCHAR',
-                'constraint' => 1024,
-            ],
             'created_at' => [
-                'type' => 'TIMESTAMP',
+                'type' => 'DATETIME',
             ],
             'updated_at' => [
-                'type' => 'TIMESTAMP',
+                'type' => 'DATETIME',
             ],
         ]);
         $this->forge->addKey('id', true);
diff --git a/app/Database/Migrations/2020-06-08-120000_add_analytics_podcasts.php b/app/Database/Migrations/2020-06-08-120000_add_analytics_podcasts.php
index 041a195a98109a3230ce4d04b77b8d910fb0eb7e..96b1419fcbc0ee4671244f71b64e3c500505aad4 100644
--- a/app/Database/Migrations/2020-06-08-120000_add_analytics_podcasts.php
+++ b/app/Database/Migrations/2020-06-08-120000_add_analytics_podcasts.php
@@ -18,21 +18,28 @@ class AddAnalyticsPodcasts extends Migration
     {
         $this->forge->addField([
             'podcast_id' => [
-                'type' => 'BIGINT',
-                'constraint' => 20,
+                'type' => 'INT',
                 'unsigned' => true,
             ],
             'date' => [
-                'type' => 'date',
+                'type' => 'DATE',
             ],
-            'hits' => [
+            'duration' => [
                 'type' => 'INT',
-                'constraint' => 10,
-                'default' => 1,
+                'unsigned' => true,
+            ],
+            'bandwidth' => [
+                'type' => 'BIGINT',
+                'unsigned' => true,
             ],
             'unique_listeners' => [
                 'type' => 'INT',
-                'constraint' => 10,
+                'unsigned' => true,
+                'default' => 1,
+            ],
+            'hits' => [
+                'type' => 'INT',
+                'unsigned' => true,
                 'default' => 1,
             ],
         ]);
diff --git a/app/Database/Migrations/2020-06-08-130000_add_analytics_podcasts_by_episode.php b/app/Database/Migrations/2020-06-08-130000_add_analytics_podcasts_by_episode.php
index c9c50221ea13651da5909077450a581bb23e4b86..546e918127e5b9c7443bb5baa96b48939fe3b593 100644
--- a/app/Database/Migrations/2020-06-08-130000_add_analytics_podcasts_by_episode.php
+++ b/app/Database/Migrations/2020-06-08-130000_add_analytics_podcasts_by_episode.php
@@ -18,26 +18,24 @@ class AddAnalyticsPodcastsByEpisode extends Migration
     {
         $this->forge->addField([
             'podcast_id' => [
-                'type' => 'BIGINT',
-                'constraint' => 20,
+                'type' => 'INT',
                 'unsigned' => true,
             ],
             'date' => [
-                'type' => 'date',
+                'type' => 'DATE',
             ],
             'episode_id' => [
-                'type' => 'BIGINT',
-                'constraint' => 20,
+                'type' => 'INT',
                 'unsigned' => true,
             ],
             'age' => [
                 'type' => 'INT',
-                'constraint' => 10,
+                'comment' => 'Days since episode publication date',
                 'unsigned' => true,
             ],
             'hits' => [
                 'type' => 'INT',
-                'constraint' => 10,
+                'unsigned' => true,
                 'default' => 1,
             ],
         ]);
diff --git a/app/Database/Migrations/2020-06-08-130000_add_analytics_podcasts_by_hour.php b/app/Database/Migrations/2020-06-08-130000_add_analytics_podcasts_by_hour.php
new file mode 100644
index 0000000000000000000000000000000000000000..828e3066197ded84da00bef02c6fb4eb061427fa
--- /dev/null
+++ b/app/Database/Migrations/2020-06-08-130000_add_analytics_podcasts_by_hour.php
@@ -0,0 +1,52 @@
+<?php
+
+/**
+ * Class AddAnalyticsPodcastsByHour
+ * Creates analytics_podcasts_by_hour table in database
+ * @copyright  2020 Podlibre
+ * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
+ * @link       https://castopod.org/
+ */
+
+namespace App\Database\Migrations;
+
+use CodeIgniter\Database\Migration;
+
+class AddAnalyticsPodcastsByHour extends Migration
+{
+    public function up()
+    {
+        $this->forge->addField([
+            'podcast_id' => [
+                'type' => 'INT',
+                'unsigned' => true,
+            ],
+            'date' => [
+                'type' => 'DATE',
+            ],
+            'hour' => [
+                'type' => 'INT',
+                'unsigned' => true,
+            ],
+            'hits' => [
+                'type' => 'INT',
+                'unsigned' => true,
+                'default' => 1,
+            ],
+        ]);
+        $this->forge->addPrimaryKey(['podcast_id', 'date', 'hour']);
+        $this->forge->addField(
+            '`created_at` timestamp NOT NULL DEFAULT current_timestamp()'
+        );
+        $this->forge->addField(
+            '`updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp()'
+        );
+        $this->forge->addForeignKey('podcast_id', 'podcasts', 'id');
+        $this->forge->createTable('analytics_podcasts_by_hour');
+    }
+
+    public function down()
+    {
+        $this->forge->dropTable('analytics_podcasts_by_hour');
+    }
+}
diff --git a/app/Database/Migrations/2020-06-08-140000_add_analytics_podcasts_by_player.php b/app/Database/Migrations/2020-06-08-140000_add_analytics_podcasts_by_player.php
index 192ebd07fb70888e78f8eafc02b981ec068997bf..a05d73526d54e6f81fb9a686eed3cf643e0755e1 100644
--- a/app/Database/Migrations/2020-06-08-140000_add_analytics_podcasts_by_player.php
+++ b/app/Database/Migrations/2020-06-08-140000_add_analytics_podcasts_by_player.php
@@ -18,12 +18,11 @@ class AddAnalyticsPodcastsByPlayer extends Migration
     {
         $this->forge->addField([
             'podcast_id' => [
-                'type' => 'BIGINT',
-                'constraint' => 20,
+                'type' => 'INT',
                 'unsigned' => true,
             ],
             'date' => [
-                'type' => 'date',
+                'type' => 'DATE',
             ],
             'service' => [
                 'type' => 'VARCHAR',
@@ -41,14 +40,14 @@ class AddAnalyticsPodcastsByPlayer extends Migration
                 'type' => 'VARCHAR',
                 'constraint' => 32,
             ],
-            'bot' => [
+            'is_bot' => [
                 'type' => 'TINYINT',
                 'constraint' => 1,
                 'default' => 0,
             ],
             'hits' => [
                 'type' => 'INT',
-                'constraint' => 10,
+                'unsigned' => true,
                 'default' => 1,
             ],
         ]);
@@ -59,7 +58,7 @@ class AddAnalyticsPodcastsByPlayer extends Migration
             'app',
             'device',
             'os',
-            'bot',
+            'is_bot',
         ]);
         $this->forge->addField(
             '`created_at` timestamp NOT NULL DEFAULT current_timestamp()'
diff --git a/app/Database/Migrations/2020-06-08-150000_add_analytics_podcasts_by_country.php b/app/Database/Migrations/2020-06-08-150000_add_analytics_podcasts_by_country.php
index 8133537570630fcb0ed871f6a5b9fb6ddedf1965..4fae6c03b661118761f51ff47cc44caec3e336db 100644
--- a/app/Database/Migrations/2020-06-08-150000_add_analytics_podcasts_by_country.php
+++ b/app/Database/Migrations/2020-06-08-150000_add_analytics_podcasts_by_country.php
@@ -18,12 +18,11 @@ class AddAnalyticsPodcastsByCountry extends Migration
     {
         $this->forge->addField([
             'podcast_id' => [
-                'type' => 'BIGINT',
-                'constraint' => 20,
+                'type' => 'INT',
                 'unsigned' => true,
             ],
             'date' => [
-                'type' => 'date',
+                'type' => 'DATE',
             ],
             'country_code' => [
                 'type' => 'VARCHAR',
@@ -32,7 +31,7 @@ class AddAnalyticsPodcastsByCountry extends Migration
             ],
             'hits' => [
                 'type' => 'INT',
-                'constraint' => 10,
+                'unsigned' => true,
                 'default' => 1,
             ],
         ]);
diff --git a/app/Database/Migrations/2020-06-08-160000_add_analytics_podcasts_by_region.php b/app/Database/Migrations/2020-06-08-160000_add_analytics_podcasts_by_region.php
index fa317996d50629a67f8e415c359e5a165c69e13b..3b7d48160df6aca88ebd026cc73501440316e957 100644
--- a/app/Database/Migrations/2020-06-08-160000_add_analytics_podcasts_by_region.php
+++ b/app/Database/Migrations/2020-06-08-160000_add_analytics_podcasts_by_region.php
@@ -18,12 +18,11 @@ class AddAnalyticsPodcastsByRegion extends Migration
     {
         $this->forge->addField([
             'podcast_id' => [
-                'type' => 'BIGINT',
-                'constraint' => 20,
+                'type' => 'INT',
                 'unsigned' => true,
             ],
             'date' => [
-                'type' => 'date',
+                'type' => 'DATE',
             ],
             'country_code' => [
                 'type' => 'VARCHAR',
@@ -45,7 +44,7 @@ class AddAnalyticsPodcastsByRegion extends Migration
             ],
             'hits' => [
                 'type' => 'INT',
-                'constraint' => 10,
+                'unsigned' => true,
                 'default' => 1,
             ],
         ]);
diff --git a/app/Database/Migrations/2020-06-08-160000_add_platform_links.php b/app/Database/Migrations/2020-06-08-160000_add_podcasts_platforms.php
similarity index 78%
rename from app/Database/Migrations/2020-06-08-160000_add_platform_links.php
rename to app/Database/Migrations/2020-06-08-160000_add_podcasts_platforms.php
index cf0a3be0dd244c08a334dcec2cfd348a765845bb..da9a15b152f87700e8adffa36612e34429203ff7 100644
--- a/app/Database/Migrations/2020-06-08-160000_add_platform_links.php
+++ b/app/Database/Migrations/2020-06-08-160000_add_podcasts_platforms.php
@@ -13,37 +13,36 @@ namespace App\Database\Migrations;
 
 use CodeIgniter\Database\Migration;
 
-class AddPlatformLinks extends Migration
+class AddPodcastsPlatforms extends Migration
 {
     public function up()
     {
         $this->forge->addField([
             'podcast_id' => [
-                'type' => 'BIGINT',
-                'constraint' => 20,
+                'type' => 'INT',
                 'unsigned' => true,
             ],
             'platform_id' => [
-                'type' => 'BIGINT',
-                'constraint' => 20,
+                'type' => 'INT',
                 'unsigned' => true,
             ],
             'link_url' => [
                 'type' => 'VARCHAR',
-                'constraint' => 191,
+                'constraint' => 512,
             ],
-            'visible' => [
+            'is_visible' => [
                 'type' => 'TINYINT',
                 'constraint' => 1,
                 'default' => 0,
             ],
             'created_at' => [
-                'type' => 'TIMESTAMP',
+                'type' => 'DATETIME',
             ],
             'updated_at' => [
-                'type' => 'TIMESTAMP',
+                'type' => 'DATETIME',
             ],
         ]);
+
         $this->forge->addPrimaryKey(['podcast_id', 'platform_id']);
         $this->forge->addForeignKey('podcast_id', 'podcasts', 'id');
         $this->forge->addForeignKey('platform_id', 'platforms', 'id');
diff --git a/app/Database/Migrations/2020-06-08-170000_add_analytics_website_by_browser.php b/app/Database/Migrations/2020-06-08-170000_add_analytics_website_by_browser.php
index a99ebf1985c87cfe8db93f9ef99db0bbeea41afc..bb445b5d13915d965e5144abcb4ca7c1eba8bd95 100644
--- a/app/Database/Migrations/2020-06-08-170000_add_analytics_website_by_browser.php
+++ b/app/Database/Migrations/2020-06-08-170000_add_analytics_website_by_browser.php
@@ -18,12 +18,11 @@ class AddAnalyticsWebsiteByBrowser extends Migration
     {
         $this->forge->addField([
             'podcast_id' => [
-                'type' => 'BIGINT',
-                'constraint' => 20,
+                'type' => 'INT',
                 'unsigned' => true,
             ],
             'date' => [
-                'type' => 'date',
+                'type' => 'DATE',
             ],
             'browser' => [
                 'type' => 'VARCHAR',
@@ -32,10 +31,11 @@ class AddAnalyticsWebsiteByBrowser extends Migration
 
             'hits' => [
                 'type' => 'INT',
-                'constraint' => 10,
+                'unsigned' => true,
                 'default' => 1,
             ],
         ]);
+
         $this->forge->addPrimaryKey(['podcast_id', 'date', 'browser']);
         $this->forge->addField(
             '`created_at` timestamp NOT NULL DEFAULT current_timestamp()'
diff --git a/app/Database/Migrations/2020-06-08-180000_add_analytics_website_by_referer.php b/app/Database/Migrations/2020-06-08-180000_add_analytics_website_by_referer.php
index 4addc2e25c9662c87a4cc8cd259dff4da423cbc3..ca761a5634642d04a2f68dc67713d8d330c94423 100644
--- a/app/Database/Migrations/2020-06-08-180000_add_analytics_website_by_referer.php
+++ b/app/Database/Migrations/2020-06-08-180000_add_analytics_website_by_referer.php
@@ -18,17 +18,15 @@ class AddAnalyticsWebsiteByReferer extends Migration
     {
         $this->forge->addField([
             'podcast_id' => [
-                'type' => 'BIGINT',
-                'constraint' => 20,
+                'type' => 'INT',
                 'unsigned' => true,
             ],
             'date' => [
-                'type' => 'date',
+                'type' => 'DATE',
             ],
-            'referer' => [
+            'referer_url' => [
                 'type' => 'VARCHAR',
                 'constraint' => 512,
-                'comment' => 'Referer URL.',
             ],
             'domain' => [
                 'type' => 'VARCHAR',
@@ -37,16 +35,16 @@ class AddAnalyticsWebsiteByReferer extends Migration
             ],
             'keywords' => [
                 'type' => 'VARCHAR',
-                'constraint' => 384,
+                'constraint' => 384, // length of referer_url (512) - domain (128)
                 'null' => true,
             ],
             'hits' => [
                 'type' => 'INT',
-                'constraint' => 10,
+                'unsigned' => true,
                 'default' => 1,
             ],
         ]);
-        $this->forge->addPrimaryKey(['podcast_id', 'date', 'referer']);
+        $this->forge->addPrimaryKey(['podcast_id', 'date', 'referer_url']);
         $this->forge->addField(
             '`created_at` timestamp NOT NULL DEFAULT current_timestamp()'
         );
diff --git a/app/Database/Migrations/2020-06-08-190000_add_analytics_website_by_entry_page.php b/app/Database/Migrations/2020-06-08-190000_add_analytics_website_by_entry_page.php
index 78355e86798bfaa72d2feda2d20685b3f2243934..2203d17fb950806c2518a8f3c4d0dcde83f5448f 100644
--- a/app/Database/Migrations/2020-06-08-190000_add_analytics_website_by_entry_page.php
+++ b/app/Database/Migrations/2020-06-08-190000_add_analytics_website_by_entry_page.php
@@ -18,25 +18,23 @@ class AddAnalyticsWebsiteByEntryPage extends Migration
     {
         $this->forge->addField([
             'podcast_id' => [
-                'type' => 'BIGINT',
-                'constraint' => 20,
+                'type' => 'INT',
                 'unsigned' => true,
             ],
             'date' => [
-                'type' => 'date',
+                'type' => 'DATE',
             ],
-            'entry_page' => [
+            'entry_page_url' => [
                 'type' => 'VARCHAR',
                 'constraint' => 512,
-                'comment' => 'Entry page URL.',
             ],
             'hits' => [
                 'type' => 'INT',
-                'constraint' => 10,
+                'unsigned' => true,
                 'default' => 1,
             ],
         ]);
-        $this->forge->addPrimaryKey(['podcast_id', 'date', 'entry_page']);
+        $this->forge->addPrimaryKey(['podcast_id', 'date', 'entry_page_url']);
         $this->forge->addField(
             '`created_at` timestamp NOT NULL DEFAULT current_timestamp()'
         );
diff --git a/app/Database/Migrations/2020-06-08-210000_add_analytics_unknown_useragents.php b/app/Database/Migrations/2020-06-08-210000_add_analytics_unknown_useragents.php
index 9327e2abdc46cb23d47281b37dae3614695890a3..1f57fd7c5ec8ff785e3ebc6baf32d29edf7e9206 100644
--- a/app/Database/Migrations/2020-06-08-210000_add_analytics_unknown_useragents.php
+++ b/app/Database/Migrations/2020-06-08-210000_add_analytics_unknown_useragents.php
@@ -18,8 +18,7 @@ class AddAnalyticsUnknownUseragents extends Migration
     {
         $this->forge->addField([
             'id' => [
-                'type' => 'BIGINT',
-                'constraint' => 20,
+                'type' => 'INT',
                 'unsigned' => true,
                 'auto_increment' => true,
             ],
@@ -30,12 +29,12 @@ class AddAnalyticsUnknownUseragents extends Migration
             ],
             'hits' => [
                 'type' => 'INT',
-                'constraint' => 10,
+                'unsigned' => true,
                 'default' => 1,
             ],
         ]);
         $this->forge->addKey('id', true);
-        // `created_at` and `updated_at` are created with SQL because Model class won’t be used for insertion (Stored Procedure will be used instead)
+        // `created_at` and `updated_at` are created with SQL because Model class won’t be used for insertion (Procedure will be used instead)
         $this->forge->addField(
             '`created_at` timestamp NOT NULL DEFAULT current_timestamp()'
         );
diff --git a/app/Database/Migrations/2020-06-11-210000_add_analytics_podcasts_stored_procedure.php b/app/Database/Migrations/2020-06-11-210000_add_analytics_podcasts_procedure.php
similarity index 61%
rename from app/Database/Migrations/2020-06-11-210000_add_analytics_podcasts_stored_procedure.php
rename to app/Database/Migrations/2020-06-11-210000_add_analytics_podcasts_procedure.php
index 9978a59f0b003f99e4cd332e4ffd75079cb273a6..01c9ab3b567f88b3a3b6b5cbf7f4d5a11c08fae1 100644
--- a/app/Database/Migrations/2020-06-11-210000_add_analytics_podcasts_stored_procedure.php
+++ b/app/Database/Migrations/2020-06-11-210000_add_analytics_podcasts_procedure.php
@@ -1,8 +1,8 @@
 <?php
 
 /**
- * Class AddAnalyticsPodcastsStoredProcedure
- * Creates analytics_podcasts stored procedure in database
+ * Class AddAnalyticsPodcastsProcedure
+ * Creates analytics_podcasts procedure in database
  * @copyright  2020 Podlibre
  * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
  * @link       https://castopod.org/
@@ -12,18 +12,18 @@ namespace App\Database\Migrations;
 
 use CodeIgniter\Database\Migration;
 
-class AddAnalyticsPodcastsStoredProcedure extends Migration
+class AddAnalyticsPodcastsProcedure extends Migration
 {
     public function up()
     {
-        // Creates Stored Procedure for data insertion
+        // Creates Procedure for data insertion
         // Example: CALL analytics_podcasts(1, 2, 'FR', 'IDF', 48.853, 2.349, PodcastAddict, 'phone', 'android', 0, 1);
         $prefix = $this->db->getPrefix();
 
         $createQuery = <<<EOD
 CREATE PROCEDURE `{$prefix}analytics_podcasts` (
-    IN `p_podcast_id` BIGINT(20) UNSIGNED,
-    IN `p_episode_id` BIGINT(20) UNSIGNED,
+    IN `p_podcast_id` INT UNSIGNED,
+    IN `p_episode_id` INT UNSIGNED,
     IN `p_country_code` VARCHAR(3) CHARSET utf8mb4,
     IN `p_region_code` VARCHAR(3) CHARSET utf8mb4,
     IN `p_latitude` FLOAT,
@@ -33,28 +33,42 @@ CREATE PROCEDURE `{$prefix}analytics_podcasts` (
     IN `p_device` VARCHAR(32) CHARSET utf8mb4,
     IN `p_os` VARCHAR(32) CHARSET utf8mb4,
     IN `p_bot` TINYINT(1) UNSIGNED,
+    IN `p_filesize` INT UNSIGNED,
+    IN `p_duration` INT UNSIGNED,
     IN `p_new_listener` TINYINT(1) UNSIGNED
     )  MODIFIES SQL DATA
 DETERMINISTIC
 SQL SECURITY INVOKER
 COMMENT 'Add one hit in podcast logs tables.'
 BEGIN
+
+SET @current_datetime = NOW();
+SET @current_date = DATE(@current_datetime);
+SET @current_hour = HOUR(@current_datetime);
+
 IF NOT `p_bot` THEN
-    INSERT INTO `{$prefix}analytics_podcasts`(`podcast_id`, `date`) 
-        VALUES (p_podcast_id, DATE(NOW())) 
-        ON DUPLICATE KEY UPDATE `hits`=`hits`+1, `unique_listeners`=`unique_listeners`+`p_new_listener`;
-    INSERT INTO `{$prefix}analytics_podcasts_by_episode`(`podcast_id`, `episode_id`, `date`, `age`) 
-    SELECT p_podcast_id, p_episode_id, DATE(NOW()), datediff(now(),`published_at`) FROM `{$prefix}episodes` WHERE `id`= p_episode_id
+    INSERT INTO `{$prefix}analytics_podcasts`(`podcast_id`, `date`)
+        VALUES (p_podcast_id, @current_date)
+        ON DUPLICATE KEY UPDATE
+            `duration`=`duration`+`p_duration`,
+            `bandwidth`=`bandwidth`+`p_filesize`,
+            `hits`=`hits`+1,
+            `unique_listeners`=`unique_listeners`+`p_new_listener`;
+    INSERT INTO `{$prefix}analytics_podcasts_by_hour`(`podcast_id`, `date`, `hour`)
+        VALUES (p_podcast_id, @current_date, @current_hour)
+        ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
+    INSERT INTO `{$prefix}analytics_podcasts_by_episode`(`podcast_id`, `episode_id`, `date`, `age`)
+    SELECT p_podcast_id, p_episode_id, @current_date, datediff(@current_datetime,`published_at`) FROM `{$prefix}episodes` WHERE `id`= p_episode_id
         ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
     INSERT INTO `{$prefix}analytics_podcasts_by_country`(`podcast_id`, `country_code`, `date`) 
-        VALUES (p_podcast_id, p_country_code, DATE(NOW())) 
+        VALUES (p_podcast_id, p_country_code, @current_date) 
         ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
     INSERT INTO `{$prefix}analytics_podcasts_by_region`(`podcast_id`, `country_code`, `region_code`, `latitude`, `longitude`, `date`) 
-        VALUES (p_podcast_id, p_country_code, p_region_code, p_latitude, p_longitude, DATE(NOW())) 
+        VALUES (p_podcast_id, p_country_code, p_region_code, p_latitude, p_longitude, @current_date) 
         ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
 END IF;
-INSERT INTO `{$prefix}analytics_podcasts_by_player`(`podcast_id`, `service`, `app`, `device`, `os`, `bot`, `date`) 
-    VALUES (p_podcast_id, p_service, p_app, p_device, p_os, p_bot, DATE(NOW())) 
+INSERT INTO `{$prefix}analytics_podcasts_by_player`(`podcast_id`, `service`, `app`, `device`, `os`, `is_bot`, `date`) 
+    VALUES (p_podcast_id, p_service, p_app, p_device, p_os, p_bot, @current_date) 
     ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
 END
 EOD;
diff --git a/app/Database/Migrations/2020-06-11-210000_add_analytics_unknown_useragents_stored_procedure.php b/app/Database/Migrations/2020-06-11-210000_add_analytics_unknown_useragents_procedure.php
similarity index 80%
rename from app/Database/Migrations/2020-06-11-210000_add_analytics_unknown_useragents_stored_procedure.php
rename to app/Database/Migrations/2020-06-11-210000_add_analytics_unknown_useragents_procedure.php
index eef223943d144fc51c5cd9de7694915dcf81a902..6b05164dda243fc7b261295bb045e55df1541cf3 100644
--- a/app/Database/Migrations/2020-06-11-210000_add_analytics_unknown_useragents_stored_procedure.php
+++ b/app/Database/Migrations/2020-06-11-210000_add_analytics_unknown_useragents_procedure.php
@@ -1,8 +1,8 @@
 <?php
 
 /**
- * Class AddAnalyticsUnknownUseragentsStoredProcedure
- * Creates analytics_unknown_useragents stored procedure in database
+ * Class AddAnalyticsUnknownUseragentsProcedure
+ * Creates analytics_unknown_useragents procedure in database
  * @copyright  2020 Podlibre
  * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
  * @link       https://castopod.org/
@@ -12,11 +12,11 @@ namespace App\Database\Migrations;
 
 use CodeIgniter\Database\Migration;
 
-class AddAnalyticsUnknownUseragentsStoredProcedure extends Migration
+class AddAnalyticsUnknownUseragentsProcedure extends Migration
 {
     public function up()
     {
-        // Creates Stored Procedure for data insertion
+        // Creates Procedure for data insertion
         // Example: CALL analytics_unknown_useragents('Podcasts/1430.46 CFNetwork/1125.2 Darwin/19.4.0');
         $procedureName = $this->db->prefixTable('analytics_unknown_useragents');
         $createQuery = <<<EOD
diff --git a/app/Database/Migrations/2020-06-11-210000_add_analytics_website_stored_procedure.php b/app/Database/Migrations/2020-06-11-210000_add_analytics_website_procedure.php
similarity index 57%
rename from app/Database/Migrations/2020-06-11-210000_add_analytics_website_stored_procedure.php
rename to app/Database/Migrations/2020-06-11-210000_add_analytics_website_procedure.php
index 836b5d7d37612f07d1b773cc25b8f9242c2fa053..8d46ad7ff9b8a0da71616edc0385127520a24504 100644
--- a/app/Database/Migrations/2020-06-11-210000_add_analytics_website_stored_procedure.php
+++ b/app/Database/Migrations/2020-06-11-210000_add_analytics_website_procedure.php
@@ -1,7 +1,7 @@
 <?php
 
 /**
- * Class AddAnalyticsWebsiteStoredProcedure
+ * Class AddAnalyticsWebsiteProcedure
  * Creates analytics_website stored procedure in database
  * @copyright  2020 Podlibre
  * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@@ -12,27 +12,30 @@ namespace App\Database\Migrations;
 
 use CodeIgniter\Database\Migration;
 
-class AddAnalyticsWebsiteStoredProcedure extends Migration
+class AddAnalyticsWebsiteProcedure extends Migration
 {
     public function up()
     {
-        // Creates Stored Procedure for data insertion
+        // Creates Procedure for data insertion
         // Example: CALL analytics_website(1,'FR','Firefox');
         $procedureName = $this->db->prefixTable('analytics_website');
         $createQuery = <<<EOD
-CREATE PROCEDURE `$procedureName` (IN `p_podcast_id` BIGINT(20) UNSIGNED, IN `p_browser` VARCHAR(191) CHARSET utf8mb4, IN `p_entry_page` VARCHAR(512) CHARSET utf8mb4, IN `p_referer` VARCHAR(512) CHARSET utf8mb4, IN `p_domain` VARCHAR(128) CHARSET utf8mb4, IN `p_keywords` VARCHAR(384) CHARSET utf8mb4)  MODIFIES SQL DATA
+CREATE PROCEDURE `$procedureName` (IN `p_podcast_id` INT UNSIGNED, IN `p_browser` VARCHAR(191) CHARSET utf8mb4, IN `p_entry_page` VARCHAR(512) CHARSET utf8mb4, IN `p_referer_url` VARCHAR(512) CHARSET utf8mb4, IN `p_domain` VARCHAR(128) CHARSET utf8mb4, IN `p_keywords` VARCHAR(384) CHARSET utf8mb4)  MODIFIES SQL DATA
 DETERMINISTIC
 SQL SECURITY INVOKER
 COMMENT 'Add one hit in website logs tables.'
 BEGIN
+
+SET @current_date = DATE(NOW());
+
 INSERT INTO {$procedureName}_by_browser(`podcast_id`, `browser`, `date`) 
-    VALUES (p_podcast_id, p_browser, DATE(NOW())) 
+    VALUES (p_podcast_id, p_browser, @current_date) 
     ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
-INSERT INTO {$procedureName}_by_referer(`podcast_id`, `referer`, `domain`, `keywords`, `date`) 
-    VALUES (p_podcast_id, p_referer, p_domain, p_keywords, DATE(NOW())) 
+INSERT INTO {$procedureName}_by_referer(`podcast_id`, `referer_url`, `domain`, `keywords`, `date`) 
+    VALUES (p_podcast_id, p_referer_url, p_domain, p_keywords, @current_date) 
     ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
-INSERT INTO {$procedureName}_by_entry_page(`podcast_id`, `entry_page`, `date`) 
-    VALUES (p_podcast_id, p_entry_page, DATE(NOW())) 
+INSERT INTO {$procedureName}_by_entry_page(`podcast_id`, `entry_page_url`, `date`) 
+    VALUES (p_podcast_id, p_entry_page, @current_date) 
     ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
 END
 EOD;
diff --git a/app/Database/Migrations/2020-07-03-191500_add_users_podcasts.php b/app/Database/Migrations/2020-07-03-191500_add_podcasts_users.php
similarity index 77%
rename from app/Database/Migrations/2020-07-03-191500_add_users_podcasts.php
rename to app/Database/Migrations/2020-07-03-191500_add_podcasts_users.php
index 3fd5fb182e5486db126711368bd4ee39d05df59c..3884d57a430a9706b7d97a7758fb7574a8830c42 100644
--- a/app/Database/Migrations/2020-07-03-191500_add_users_podcasts.php
+++ b/app/Database/Migrations/2020-07-03-191500_add_podcasts_users.php
@@ -13,24 +13,21 @@ namespace App\Database\Migrations;
 
 use CodeIgniter\Database\Migration;
 
-class AddUsersPodcasts extends Migration
+class AddPodcastsUsers extends Migration
 {
     public function up()
     {
         $this->forge->addField([
-            'user_id' => [
+            'podcast_id' => [
                 'type' => 'INT',
-                'constraint' => 11,
                 'unsigned' => true,
             ],
-            'podcast_id' => [
-                'type' => 'BIGINT',
-                'constraint' => 20,
+            'user_id' => [
+                'type' => 'INT',
                 'unsigned' => true,
             ],
             'group_id' => [
                 'type' => 'INT',
-                'constraint' => 11,
                 'unsigned' => true,
             ],
         ]);
@@ -38,11 +35,11 @@ class AddUsersPodcasts extends Migration
         $this->forge->addForeignKey('user_id', 'users', 'id');
         $this->forge->addForeignKey('podcast_id', 'podcasts', 'id');
         $this->forge->addForeignKey('group_id', 'auth_groups', 'id');
-        $this->forge->createTable('users_podcasts');
+        $this->forge->createTable('podcasts_users');
     }
 
     public function down()
     {
-        $this->forge->dropTable('users_podcasts');
+        $this->forge->dropTable('podcasts_users');
     }
 }
diff --git a/app/Database/Migrations/2020-08-17-150000_add_pages.php b/app/Database/Migrations/2020-08-17-150000_add_pages.php
index 32f22ca0c5ed216a0a3158a9214c0d41cd2d0841..b35cd443d6b9c97d52d45a80307c31908ed13319 100644
--- a/app/Database/Migrations/2020-08-17-150000_add_pages.php
+++ b/app/Database/Migrations/2020-08-17-150000_add_pages.php
@@ -20,13 +20,12 @@ class AddPages extends Migration
         $this->forge->addField([
             'id' => [
                 'type' => 'INT',
-                'constraint' => 11,
                 'unsigned' => true,
                 'auto_increment' => true,
             ],
             'title' => [
                 'type' => 'VARCHAR',
-                'constraint' => 1024,
+                'constraint' => 255,
             ],
             'slug' => [
                 'type' => 'VARCHAR',
@@ -37,10 +36,10 @@ class AddPages extends Migration
                 'type' => 'TEXT',
             ],
             'created_at' => [
-                'type' => 'TIMESTAMP',
+                'type' => 'DATETIME',
             ],
             'updated_at' => [
-                'type' => 'TIMESTAMP',
+                'type' => 'DATETIME',
             ],
             'deleted_at' => [
                 'type' => 'DATETIME',
diff --git a/app/Database/Migrations/2020-09-29-150000_add_podcasts_categories.php b/app/Database/Migrations/2020-09-29-150000_add_podcasts_categories.php
index 4139b15011199e61f78d66ea3c578d92cdd08ffb..6c0bd504648aa9fb46c8ec069a1e0e69826cc917 100644
--- a/app/Database/Migrations/2020-09-29-150000_add_podcasts_categories.php
+++ b/app/Database/Migrations/2020-09-29-150000_add_podcasts_categories.php
@@ -19,13 +19,11 @@ class AddPodcastsCategories extends Migration
     {
         $this->forge->addField([
             'podcast_id' => [
-                'type' => 'BIGINT',
-                'constraint' => 20,
+                'type' => 'INT',
                 'unsigned' => true,
             ],
             'category_id' => [
                 'type' => 'INT',
-                'constraint' => 10,
                 'unsigned' => true,
             ],
         ]);
diff --git a/app/Database/Seeds/FakePodcastsAnalyticsSeeder.php b/app/Database/Seeds/FakePodcastsAnalyticsSeeder.php
index f7156f6e2aa8b39be4bfd112c27ad3f6b8fd9340..1fc04d7542102442de1c4ea6366a1840e1a32423 100644
--- a/app/Database/Seeds/FakePodcastsAnalyticsSeeder.php
+++ b/app/Database/Seeds/FakePodcastsAnalyticsSeeder.php
@@ -46,6 +46,7 @@ class FakePodcastsAnalyticsSeeder extends Seeder
                 $date = strtotime(date('Y-m-d', $date) . ' +1 day')
             ) {
                 $analytics_podcasts = [];
+                $analytics_podcasts_by_hour = [];
                 $analytics_podcasts_by_country = [];
                 $analytics_podcasts_by_episode = [];
                 $analytics_podcasts_by_player = [];
@@ -83,7 +84,7 @@ class FakePodcastsAnalyticsSeeder extends Seeder
                             ? $player['device']
                             : '';
                         $os = isset($player['os']) ? $player['os'] : '';
-                        $bot = isset($player['bot']) ? $player['bot'] : 0;
+                        $isBot = isset($player['bot']) ? $player['bot'] : 0;
 
                         $fakeIp =
                             rand(0, 255) .
@@ -124,9 +125,17 @@ class FakePodcastsAnalyticsSeeder extends Seeder
                         $analytics_podcasts[] = [
                             'podcast_id' => $podcast->id,
                             'date' => date('Y-m-d', $date),
+                            'duration' => rand(60, 3600),
+                            'bandwidth' => rand(1000000, 10000000),
                             'hits' => $hits,
                             'unique_listeners' => $hits,
                         ];
+                        $analytics_podcasts_by_hour[] = [
+                            'podcast_id' => $podcast->id,
+                            'date' => date('Y-m-d', $date),
+                            'hour' => rand(0, 23),
+                            'hits' => $hits,
+                        ];
                         $analytics_podcasts_by_country[] = [
                             'podcast_id' => $podcast->id,
                             'date' => date('Y-m-d', $date),
@@ -143,11 +152,11 @@ class FakePodcastsAnalyticsSeeder extends Seeder
                         $analytics_podcasts_by_player[] = [
                             'podcast_id' => $podcast->id,
                             'date' => date('Y-m-d', $date),
-                            'service'=> $service,
+                            'service' => $service,
                             'app' => $app,
                             'device' => $device,
                             'os' => $os,
-                            'bot' => $bot,
+                            'is_bot' => $isBot,
                             'hits' => $hits,
                         ];
                         $analytics_podcasts_by_region[] = [
@@ -165,6 +174,10 @@ class FakePodcastsAnalyticsSeeder extends Seeder
                     ->table('analytics_podcasts')
                     ->ignore(true)
                     ->insertBatch($analytics_podcasts);
+                $this->db
+                    ->table('analytics_podcasts_by_hour')
+                    ->ignore(true)
+                    ->insertBatch($analytics_podcasts_by_hour);
                 $this->db
                     ->table('analytics_podcasts_by_country')
                     ->ignore(true)
diff --git a/app/Database/Seeds/FakeWebsiteAnalyticsSeeder.php b/app/Database/Seeds/FakeWebsiteAnalyticsSeeder.php
index 67270d4c5ef5e53cbe5d9953ce0a93461c25af1f..daa37da925ef3d9b0ffe7d03c1418e946faba446 100644
--- a/app/Database/Seeds/FakeWebsiteAnalyticsSeeder.php
+++ b/app/Database/Seeds/FakeWebsiteAnalyticsSeeder.php
@@ -226,13 +226,13 @@ class FakeWebsiteAnalyticsSeeder extends Seeder
                         $website_by_entry_page[] = [
                             'podcast_id' => $podcast->id,
                             'date' => date('Y-m-d', $date),
-                            'entry_page' => $episode->link,
+                            'entry_page_url' => $episode->link,
                             'hits' => $hits,
                         ];
                         $website_by_referer[] = [
                             'podcast_id' => $podcast->id,
                             'date' => date('Y-m-d', $date),
-                            'referer' =>
+                            'referer_url' =>
                                 'http://' . $domain . '/?q=' . $keyword,
                             'domain' => $domain,
                             'keywords' => $keyword,
diff --git a/app/Database/Seeds/LanguageSeeder.php b/app/Database/Seeds/LanguageSeeder.php
index 31fee8fc7c8b9d028fcb9f07054fe6be47db827a..b2912c3f657e08b6752ba7004435ea70188fe169 100644
--- a/app/Database/Seeds/LanguageSeeder.php
+++ b/app/Database/Seeds/LanguageSeeder.php
@@ -24,613 +24,506 @@ class LanguageSeeder extends Seeder
     public function run()
     {
         $data = [
-            ['code' => 'aa', 'name' => 'Afar', 'native_name' => 'Afaraf'],
+            ['code' => 'aa', 'native_name' => 'Afaraf'],
             [
                 'code' => 'ab',
-                'name' => 'Abkhazian',
                 'native_name' => 'аҧсуа бызшәа, аҧсшәа',
             ],
-            ['code' => 'ae', 'name' => 'Avestan', 'native_name' => 'avesta'],
+            ['code' => 'ae', 'native_name' => 'avesta'],
             [
                 'code' => 'af',
-                'name' => 'Afrikaans',
                 'native_name' => 'Afrikaans',
             ],
-            ['code' => 'ak', 'name' => 'Akan', 'native_name' => 'Akan'],
-            ['code' => 'am', 'name' => 'Amharic', 'native_name' => 'አማርኛ'],
+            ['code' => 'ak', 'native_name' => 'Akan'],
+            ['code' => 'am', 'native_name' => 'አማርኛ'],
             [
                 'code' => 'an',
-                'name' => 'Aragonese',
                 'native_name' => 'aragonés',
             ],
-            ['code' => 'ar', 'name' => 'Arabic', 'native_name' => 'العربية'],
-            ['code' => 'as', 'name' => 'Assamese', 'native_name' => 'অসমীয়া'],
+            ['code' => 'ar', 'native_name' => 'العربية'],
+            ['code' => 'as', 'native_name' => 'অসমীয়া'],
             [
                 'code' => 'av',
-                'name' => 'Avaric',
                 'native_name' => 'авар мацӀ, магӀарул мацӀ',
             ],
-            ['code' => 'ay', 'name' => 'Aymara', 'native_name' => 'aymar aru'],
+            ['code' => 'ay', 'native_name' => 'aymar aru'],
             [
                 'code' => 'az',
-                'name' => 'Azerbaijani',
                 'native_name' => 'azərbaycan dili',
             ],
             [
                 'code' => 'ba',
-                'name' => 'Bashkir',
                 'native_name' => 'башҡорт теле',
             ],
             [
                 'code' => 'be',
-                'name' => 'Belarusian',
                 'native_name' => 'беларуская мова',
             ],
             [
                 'code' => 'bg',
-                'name' => 'Bulgarian',
                 'native_name' => 'български език',
             ],
             [
                 'code' => 'bh',
-                'name' => 'Bihari languages',
                 'native_name' => 'भोजपुरी',
             ],
-            ['code' => 'bi', 'name' => 'Bislama', 'native_name' => 'Bislama'],
+            ['code' => 'bi', 'native_name' => 'Bislama'],
             [
                 'code' => 'bm',
-                'name' => 'Bambara',
                 'native_name' => 'bamanankan',
             ],
-            ['code' => 'bn', 'name' => 'Bengali', 'native_name' => 'বাংলা'],
-            ['code' => 'bo', 'name' => 'Tibetan', 'native_name' => 'བོད་ཡིག'],
-            ['code' => 'br', 'name' => 'Breton', 'native_name' => 'brezhoneg'],
+            ['code' => 'bn', 'native_name' => 'বাংলা'],
+            ['code' => 'bo', 'native_name' => 'བོད་ཡིག'],
+            ['code' => 'br', 'native_name' => 'brezhoneg'],
             [
                 'code' => 'bs',
-                'name' => 'Bosnian',
                 'native_name' => 'bosanski jezik',
             ],
             [
                 'code' => 'ca',
-                'name' => 'Catalan, Valencian',
                 'native_name' => 'català, valencià',
             ],
             [
                 'code' => 'ce',
-                'name' => 'Chechen',
                 'native_name' => 'нохчийн мотт',
             ],
-            ['code' => 'ch', 'name' => 'Chamorro', 'native_name' => 'Chamoru'],
+            ['code' => 'ch', 'native_name' => 'Chamoru'],
             [
                 'code' => 'co',
-                'name' => 'Corsican',
                 'native_name' => 'corsu, lingua corsa',
             ],
-            ['code' => 'cr', 'name' => 'Cree', 'native_name' => 'ᓀᐦᐃᔭᐍᐏᐣ'],
+            ['code' => 'cr', 'native_name' => 'ᓀᐦᐃᔭᐍᐏᐣ'],
             [
                 'code' => 'cs',
-                'name' => 'Czech',
                 'native_name' => 'čeština, český jazyk',
             ],
             [
                 'code' => 'cu',
-                'name' =>
-                    'Church Slavic, Old Slavonic, Church Slavonic, Old Bulgarian, Old Church Slavonic',
                 'native_name' => 'ѩзыкъ словѣньскъ',
             ],
             [
                 'code' => 'cv',
-                'name' => 'Chuvash',
                 'native_name' => 'чӑваш чӗлхи',
             ],
-            ['code' => 'cy', 'name' => 'Welsh', 'native_name' => 'Cymraeg'],
-            ['code' => 'da', 'name' => 'Danish', 'native_name' => 'dansk'],
-            ['code' => 'de', 'name' => 'German', 'native_name' => 'Deutsch'],
+            ['code' => 'cy', 'native_name' => 'Cymraeg'],
+            ['code' => 'da', 'native_name' => 'dansk'],
+            ['code' => 'de', 'native_name' => 'Deutsch'],
             [
                 'code' => 'dv',
-                'name' => 'Divehi, Dhivehi, Maldivian',
                 'native_name' => 'Þ‹Þ¨ÞˆÞ¬Þ€Þ¨',
             ],
-            ['code' => 'dz', 'name' => 'Dzongkha', 'native_name' => 'རྫོང་ཁ'],
-            ['code' => 'ee', 'name' => 'Ewe', 'native_name' => 'EÊ‹egbe'],
+            ['code' => 'dz', 'native_name' => 'རྫོང་ཁ'],
+            ['code' => 'ee', 'native_name' => 'EÊ‹egbe'],
             [
                 'code' => 'el',
-                'name' => 'Greek, Modern (1453–)',
                 'native_name' => 'ελληνικά',
             ],
-            ['code' => 'en', 'name' => 'English', 'native_name' => 'English'],
+            ['code' => 'en', 'native_name' => 'English'],
             [
                 'code' => 'eo',
-                'name' => 'Esperanto',
                 'native_name' => 'Esperanto',
             ],
             [
                 'code' => 'es',
-                'name' => 'Spanish, Castilian',
                 'native_name' => 'Español',
             ],
             [
                 'code' => 'et',
-                'name' => 'Estonian',
                 'native_name' => 'eesti, eesti keel',
             ],
             [
                 'code' => 'eu',
-                'name' => 'Basque',
                 'native_name' => 'euskara, euskera',
             ],
-            ['code' => 'fa', 'name' => 'Persian', 'native_name' => 'فارسی'],
+            ['code' => 'fa', 'native_name' => 'فارسی'],
             [
                 'code' => 'ff',
-                'name' => 'Fulah',
                 'native_name' => 'Fulfulde, Pulaar, Pular',
             ],
             [
                 'code' => 'fi',
-                'name' => 'Finnish',
                 'native_name' => 'suomi, suomen kieli',
             ],
             [
                 'code' => 'fj',
-                'name' => 'Fijian',
                 'native_name' => 'vosa Vakaviti',
             ],
-            ['code' => 'fo', 'name' => 'Faroese', 'native_name' => 'føroyskt'],
+            ['code' => 'fo', 'native_name' => 'føroyskt'],
             [
                 'code' => 'fr',
-                'name' => 'French',
                 'native_name' => 'français, langue française',
             ],
             [
                 'code' => 'fy',
-                'name' => 'Western Frisian',
                 'native_name' => 'Frysk',
             ],
-            ['code' => 'ga', 'name' => 'Irish', 'native_name' => 'Gaeilge'],
+            ['code' => 'ga', 'native_name' => 'Gaeilge'],
             [
                 'code' => 'gd',
-                'name' => 'Gaelic, Scottish Gaelic',
                 'native_name' => 'Gàidhlig',
             ],
-            ['code' => 'gl', 'name' => 'Galician', 'native_name' => 'Galego'],
-            ['code' => 'gn', 'name' => 'Guarani', 'native_name' => 'Avañe\'ẽ'],
-            ['code' => 'gu', 'name' => 'Gujarati', 'native_name' => 'ગુજરાતી'],
+            ['code' => 'gl', 'native_name' => 'Galego'],
+            ['code' => 'gn', 'native_name' => 'Avañe\'ẽ'],
+            ['code' => 'gu', 'native_name' => 'ગુજરાતી'],
             [
                 'code' => 'gv',
-                'name' => 'Manx',
                 'native_name' => 'Gaelg, Gailck',
             ],
             [
                 'code' => 'ha',
-                'name' => 'Hausa',
                 'native_name' => '(Hausa) هَوُسَ',
             ],
-            ['code' => 'he', 'name' => 'Hebrew', 'native_name' => 'עברית'],
+            ['code' => 'he', 'native_name' => 'עברית'],
             [
                 'code' => 'hi',
-                'name' => 'Hindi',
                 'native_name' => 'हिन्दी, हिंदी',
             ],
             [
                 'code' => 'ho',
-                'name' => 'Hiri Motu',
                 'native_name' => 'Hiri Motu',
             ],
             [
                 'code' => 'hr',
-                'name' => 'Croatian',
                 'native_name' => 'hrvatski jezik',
             ],
             [
                 'code' => 'ht',
-                'name' => 'Haitian, Haitian Creole',
                 'native_name' => 'Kreyòl ayisyen',
             ],
-            ['code' => 'hu', 'name' => 'Hungarian', 'native_name' => 'magyar'],
-            ['code' => 'hy', 'name' => 'Armenian', 'native_name' => 'Õ€Õ¡ÕµÕ¥Ö€Õ¥Õ¶'],
-            ['code' => 'hz', 'name' => 'Herero', 'native_name' => 'Otjiherero'],
+            ['code' => 'hu', 'native_name' => 'magyar'],
+            ['code' => 'hy', 'native_name' => 'Õ€Õ¡ÕµÕ¥Ö€Õ¥Õ¶'],
+            ['code' => 'hz', 'native_name' => 'Otjiherero'],
             [
                 'code' => 'ia',
-                'name' =>
-                    'Interlingua (International Auxiliary Language Association)',
                 'native_name' => 'Interlingua',
             ],
             [
                 'code' => 'id',
-                'name' => 'Indonesian',
                 'native_name' => 'Bahasa Indonesia',
             ],
             [
                 'code' => 'ie',
-                'name' => 'Interlingue, Occidental',
                 'native_name' =>
                     '(originally:) Occidental, (after WWII:) Interlingue',
             ],
-            ['code' => 'ig', 'name' => 'Igbo', 'native_name' => 'Asụsụ Igbo'],
+            ['code' => 'ig', 'native_name' => 'Asụsụ Igbo'],
             [
                 'code' => 'ii',
-                'name' => 'Sichuan Yi, Nuosu',
                 'native_name' => 'ꆈꌠ꒿ Nuosuhxop',
             ],
             [
                 'code' => 'ik',
-                'name' => 'Inupiaq',
                 'native_name' => 'Iñupiaq, Iñupiatun',
             ],
-            ['code' => 'io', 'name' => 'Ido', 'native_name' => 'Ido'],
+            ['code' => 'io', 'native_name' => 'Ido'],
             [
                 'code' => 'is',
-                'name' => 'Icelandic',
                 'native_name' => 'Íslenska',
             ],
-            ['code' => 'it', 'name' => 'Italian', 'native_name' => 'Italiano'],
-            ['code' => 'iu', 'name' => 'Inuktitut', 'native_name' => 'ᐃᓄᒃᑎᑐᑦ'],
+            ['code' => 'it', 'native_name' => 'Italiano'],
+            ['code' => 'iu', 'native_name' => 'ᐃᓄᒃᑎᑐᑦ'],
             [
                 'code' => 'ja',
-                'name' => 'Japanese',
                 'native_name' => '日本語 (にほんご)',
             ],
             [
                 'code' => 'jv',
-                'name' => 'Javanese',
                 'native_name' => 'ꦧꦱꦗꦮ, Basa Jawa',
             ],
-            ['code' => 'ka', 'name' => 'Georgian', 'native_name' => 'ქართული'],
-            ['code' => 'kg', 'name' => 'Kongo', 'native_name' => 'Kikongo'],
+            ['code' => 'ka', 'native_name' => 'ქართული'],
+            ['code' => 'kg', 'native_name' => 'Kikongo'],
             [
                 'code' => 'ki',
-                'name' => 'Kikuyu, Gikuyu',
                 'native_name' => 'Gĩkũyũ',
             ],
             [
                 'code' => 'kj',
-                'name' => 'Kuanyama, Kwanyama',
                 'native_name' => 'Kuanyama',
             ],
-            ['code' => 'kk', 'name' => 'Kazakh', 'native_name' => 'қазақ тілі'],
+            ['code' => 'kk', 'native_name' => 'қазақ тілі'],
             [
                 'code' => 'kl',
-                'name' => 'Kalaallisut, Greenlandic',
                 'native_name' => 'kalaallisut, kalaallit oqaasii',
             ],
             [
                 'code' => 'km',
-                'name' => 'Central Khmer',
                 'native_name' => 'ខ្មែរ, ខេមរភាសា, ភាសាខ្មែរ',
             ],
-            ['code' => 'kn', 'name' => 'Kannada', 'native_name' => 'ಕನ್ನಡ'],
-            ['code' => 'ko', 'name' => 'Korean', 'native_name' => '한국어'],
-            ['code' => 'kr', 'name' => 'Kanuri', 'native_name' => 'Kanuri'],
+            ['code' => 'kn', 'native_name' => 'ಕನ್ನಡ'],
+            ['code' => 'ko', 'native_name' => '한국어'],
+            ['code' => 'kr', 'native_name' => 'Kanuri'],
             [
                 'code' => 'ks',
-                'name' => 'Kashmiri',
                 'native_name' => 'कश्मीरी, كشميري‎',
             ],
             [
                 'code' => 'ku',
-                'name' => 'Kurdish',
                 'native_name' => 'Kurdî, کوردی‎',
             ],
-            ['code' => 'kv', 'name' => 'Komi', 'native_name' => 'коми кыв'],
-            ['code' => 'kw', 'name' => 'Cornish', 'native_name' => 'Kernewek'],
+            ['code' => 'kv', 'native_name' => 'коми кыв'],
+            ['code' => 'kw', 'native_name' => 'Kernewek'],
             [
                 'code' => 'ky',
-                'name' => 'Kirghiz, Kyrgyz',
                 'native_name' => 'Кыргызча, Кыргыз тили',
             ],
             [
                 'code' => 'la',
-                'name' => 'Latin',
                 'native_name' => 'latine, lingua latina',
             ],
             [
                 'code' => 'lb',
-                'name' => 'Luxembourgish, Letzeburgesch',
                 'native_name' => 'Lëtzebuergesch',
             ],
-            ['code' => 'lg', 'name' => 'Ganda', 'native_name' => 'Luganda'],
+            ['code' => 'lg', 'native_name' => 'Luganda'],
             [
                 'code' => 'li',
-                'name' => 'Limburgan, Limburger, Limburgish',
                 'native_name' => 'Limburgs',
             ],
-            ['code' => 'ln', 'name' => 'Lingala', 'native_name' => 'Lingála'],
-            ['code' => 'lo', 'name' => 'Lao', 'native_name' => 'ພາສາລາວ'],
+            ['code' => 'ln', 'native_name' => 'Lingála'],
+            ['code' => 'lo', 'native_name' => 'ພາສາລາວ'],
             [
                 'code' => 'lt',
-                'name' => 'Lithuanian',
                 'native_name' => 'lietuvių kalba',
             ],
             [
                 'code' => 'lu',
-                'name' => 'Luba-Katanga',
                 'native_name' => 'Kiluba',
             ],
             [
                 'code' => 'lv',
-                'name' => 'Latvian',
                 'native_name' => 'latviešu valoda',
             ],
             [
                 'code' => 'mg',
-                'name' => 'Malagasy',
                 'native_name' => 'fiteny malagasy',
             ],
             [
                 'code' => 'mh',
-                'name' => 'Marshallese',
                 'native_name' => 'Kajin M̧ajeļ',
             ],
             [
                 'code' => 'mi',
-                'name' => 'Maori',
                 'native_name' => 'te reo Māori',
             ],
             [
                 'code' => 'mk',
-                'name' => 'Macedonian',
                 'native_name' => 'македонски јазик',
             ],
-            ['code' => 'ml', 'name' => 'Malayalam', 'native_name' => 'മലയാളം'],
+            ['code' => 'ml', 'native_name' => 'മലയാളം'],
             [
                 'code' => 'mn',
-                'name' => 'Mongolian',
                 'native_name' => 'Монгол хэл',
             ],
-            ['code' => 'mr', 'name' => 'Marathi', 'native_name' => 'मराठी'],
+            ['code' => 'mr', 'native_name' => 'मराठी'],
             [
                 'code' => 'ms',
-                'name' => 'Malay',
                 'native_name' => 'Bahasa Melayu, بهاس ملايو‎',
             ],
-            ['code' => 'mt', 'name' => 'Maltese', 'native_name' => 'Malti'],
-            ['code' => 'my', 'name' => 'Burmese', 'native_name' => 'ဗမာစာ'],
+            ['code' => 'mt', 'native_name' => 'Malti'],
+            ['code' => 'my', 'native_name' => 'ဗမာစာ'],
             [
                 'code' => 'na',
-                'name' => 'Nauru',
                 'native_name' => 'Dorerin Naoero',
             ],
             [
                 'code' => 'nb',
-                'name' => 'Norwegian Bokmål',
                 'native_name' => 'Norsk Bokmål',
             ],
             [
                 'code' => 'nd',
-                'name' => 'North Ndebele',
                 'native_name' => 'isiNdebele',
             ],
-            ['code' => 'ne', 'name' => 'Nepali', 'native_name' => 'नेपाली'],
-            ['code' => 'ng', 'name' => 'Ndonga', 'native_name' => 'Owambo'],
+            ['code' => 'ne', 'native_name' => 'नेपाली'],
+            ['code' => 'ng', 'native_name' => 'Owambo'],
             [
                 'code' => 'nl',
-                'name' => 'Dutch, Flemish',
                 'native_name' => 'Nederlands, Vlaams',
             ],
             [
                 'code' => 'nn',
-                'name' => 'Norwegian Nynorsk',
                 'native_name' => 'Norsk Nynorsk',
             ],
-            ['code' => 'no', 'name' => 'Norwegian', 'native_name' => 'Norsk'],
+            ['code' => 'no', 'native_name' => 'Norsk'],
             [
                 'code' => 'nr',
-                'name' => 'South Ndebele',
                 'native_name' => 'isiNdebele',
             ],
             [
                 'code' => 'nv',
-                'name' => 'Navajo, Navaho',
                 'native_name' => 'Diné bizaad',
             ],
             [
                 'code' => 'ny',
-                'name' => 'Chichewa, Chewa, Nyanja',
                 'native_name' => 'chiCheŵa, chinyanja',
             ],
             [
                 'code' => 'oc',
-                'name' => 'Occitan',
                 'native_name' => 'occitan, lenga d’òc',
             ],
-            ['code' => 'oj', 'name' => 'Ojibwa', 'native_name' => 'ᐊᓂᔑᓈᐯᒧᐎᓐ'],
+            ['code' => 'oj', 'native_name' => 'ᐊᓂᔑᓈᐯᒧᐎᓐ'],
             [
                 'code' => 'om',
-                'name' => 'Oromo',
                 'native_name' => 'Afaan Oromoo',
             ],
-            ['code' => 'or', 'name' => 'Oriya', 'native_name' => 'ଓଡ଼ିଆ'],
+            ['code' => 'or', 'native_name' => 'ଓଡ଼ିଆ'],
             [
                 'code' => 'os',
-                'name' => 'Ossetian, Ossetic',
                 'native_name' => 'ирон æвзаг',
             ],
             [
                 'code' => 'pa',
-                'name' => 'Punjabi, Panjabi',
                 'native_name' => 'ਪੰਜਾਬੀ, پنجابی‎',
             ],
-            ['code' => 'pi', 'name' => 'Pali', 'native_name' => 'पालि, पाळि'],
+            ['code' => 'pi', 'native_name' => 'पालि, पाळि'],
             [
                 'code' => 'pl',
-                'name' => 'Polish',
                 'native_name' => 'język polski, polszczyzna',
             ],
             [
                 'code' => 'ps',
-                'name' => 'Pashto, Pushto',
                 'native_name' => 'پښتو',
             ],
             [
                 'code' => 'pt',
-                'name' => 'Portuguese',
                 'native_name' => 'Português',
             ],
             [
                 'code' => 'qu',
-                'name' => 'Quechua',
                 'native_name' => 'Runa Simi, Kichwa',
             ],
             [
                 'code' => 'rm',
-                'name' => 'Romansh',
                 'native_name' => 'Rumantsch Grischun',
             ],
-            ['code' => 'rn', 'name' => 'Rundi', 'native_name' => 'Ikirundi'],
+            ['code' => 'rn', 'native_name' => 'Ikirundi'],
             [
                 'code' => 'ro',
-                'name' => 'Romanian, Moldavian, Moldovan',
                 'native_name' => 'Română',
             ],
-            ['code' => 'ru', 'name' => 'Russian', 'native_name' => 'русский'],
+            ['code' => 'ru', 'native_name' => 'русский'],
             [
                 'code' => 'rw',
-                'name' => 'Kinyarwanda',
                 'native_name' => 'Ikinyarwanda',
             ],
             [
                 'code' => 'sa',
-                'name' => 'Sanskrit',
                 'native_name' => 'संस्कृतम्',
             ],
-            ['code' => 'sc', 'name' => 'Sardinian', 'native_name' => 'sardu'],
+            ['code' => 'sc', 'native_name' => 'sardu'],
             [
                 'code' => 'sd',
-                'name' => 'Sindhi',
                 'native_name' => 'सिन्धी, سنڌي، سندھی‎',
             ],
             [
                 'code' => 'se',
-                'name' => 'Northern Sami',
                 'native_name' => 'Davvisámegiella',
             ],
             [
                 'code' => 'sg',
-                'name' => 'Sango',
                 'native_name' => 'yângâ tî sängö',
             ],
             [
                 'code' => 'si',
-                'name' => 'Sinhala, Sinhalese',
                 'native_name' => 'සිංහල',
             ],
             [
                 'code' => 'sk',
-                'name' => 'Slovak',
                 'native_name' => 'Slovenčina, Slovenský Jazyk',
             ],
             [
                 'code' => 'sl',
-                'name' => 'Slovenian',
                 'native_name' => 'Slovenski Jezik, Slovenščina',
             ],
             [
                 'code' => 'sm',
-                'name' => 'Samoan',
                 'native_name' => 'gagana fa\'a Samoa',
             ],
-            ['code' => 'sn', 'name' => 'Shona', 'native_name' => 'chiShona'],
+            ['code' => 'sn', 'native_name' => 'chiShona'],
             [
                 'code' => 'so',
-                'name' => 'Somali',
                 'native_name' => 'Soomaaliga, af Soomaali',
             ],
-            ['code' => 'sq', 'name' => 'Albanian', 'native_name' => 'Shqip'],
+            ['code' => 'sq', 'native_name' => 'Shqip'],
             [
                 'code' => 'sr',
-                'name' => 'Serbian',
                 'native_name' => 'српски језик',
             ],
-            ['code' => 'ss', 'name' => 'Swati', 'native_name' => 'SiSwati'],
+            ['code' => 'ss', 'native_name' => 'SiSwati'],
             [
                 'code' => 'st',
-                'name' => 'Southern Sotho',
                 'native_name' => 'Sesotho',
             ],
             [
                 'code' => 'su',
-                'name' => 'Sundanese',
                 'native_name' => 'Basa Sunda',
             ],
-            ['code' => 'sv', 'name' => 'Swedish', 'native_name' => 'Svenska'],
-            ['code' => 'sw', 'name' => 'Swahili', 'native_name' => 'Kiswahili'],
-            ['code' => 'ta', 'name' => 'Tamil', 'native_name' => 'தமிழ்'],
-            ['code' => 'te', 'name' => 'Telugu', 'native_name' => 'తెలుగు'],
+            ['code' => 'sv', 'native_name' => 'Svenska'],
+            ['code' => 'sw', 'native_name' => 'Kiswahili'],
+            ['code' => 'ta', 'native_name' => 'தமிழ்'],
+            ['code' => 'te', 'native_name' => 'తెలుగు'],
             [
                 'code' => 'tg',
-                'name' => 'Tajik',
                 'native_name' => 'тоҷикӣ, toçikī, تاجیکی‎',
             ],
-            ['code' => 'th', 'name' => 'Thai', 'native_name' => 'ไทย'],
-            ['code' => 'ti', 'name' => 'Tigrinya', 'native_name' => 'ትግርኛ'],
+            ['code' => 'th', 'native_name' => 'ไทย'],
+            ['code' => 'ti', 'native_name' => 'ትግርኛ'],
             [
                 'code' => 'tk',
-                'name' => 'Turkmen',
                 'native_name' => 'Türkmen, Түркмен',
             ],
             [
                 'code' => 'tl',
-                'name' => 'Tagalog',
                 'native_name' => 'Wikang Tagalog',
             ],
-            ['code' => 'tn', 'name' => 'Tswana', 'native_name' => 'Setswana'],
+            ['code' => 'tn', 'native_name' => 'Setswana'],
             [
                 'code' => 'to',
-                'name' => 'Tonga (Tonga Islands)',
                 'native_name' => 'Faka Tonga',
             ],
-            ['code' => 'tr', 'name' => 'Turkish', 'native_name' => 'Türkçe'],
-            ['code' => 'ts', 'name' => 'Tsonga', 'native_name' => 'Xitsonga'],
+            ['code' => 'tr', 'native_name' => 'Türkçe'],
+            ['code' => 'ts', 'native_name' => 'Xitsonga'],
             [
                 'code' => 'tt',
-                'name' => 'Tatar',
                 'native_name' => 'татар теле, tatar tele',
             ],
-            ['code' => 'tw', 'name' => 'Twi', 'native_name' => 'Twi'],
+            ['code' => 'tw', 'native_name' => 'Twi'],
             [
                 'code' => 'ty',
-                'name' => 'Tahitian',
                 'native_name' => 'Reo Tahiti',
             ],
             [
                 'code' => 'ug',
-                'name' => 'Uighur, Uyghur',
                 'native_name' => 'ئۇيغۇرچە‎, Uyghurche',
             ],
             [
                 'code' => 'uk',
-                'name' => 'Ukrainian',
                 'native_name' => 'Українська',
             ],
-            ['code' => 'ur', 'name' => 'Urdu', 'native_name' => 'اردو'],
+            ['code' => 'ur', 'native_name' => 'اردو'],
             [
                 'code' => 'uz',
-                'name' => 'Uzbek',
                 'native_name' => 'Oʻzbek, Ўзбек, أۇزبېك‎',
             ],
-            ['code' => 've', 'name' => 'Venda', 'native_name' => 'Tshivenḓa'],
+            ['code' => 've', 'native_name' => 'Tshivenḓa'],
             [
                 'code' => 'vi',
-                'name' => 'Vietnamese',
                 'native_name' => 'Tiếng Việt',
             ],
-            ['code' => 'vo', 'name' => 'Volapük', 'native_name' => 'Volapük'],
-            ['code' => 'wa', 'name' => 'Walloon', 'native_name' => 'Walon'],
-            ['code' => 'wo', 'name' => 'Wolof', 'native_name' => 'Wollof'],
-            ['code' => 'xh', 'name' => 'Xhosa', 'native_name' => 'isiXhosa'],
-            ['code' => 'yi', 'name' => 'Yiddish', 'native_name' => 'ייִדיש'],
-            ['code' => 'yo', 'name' => 'Yoruba', 'native_name' => 'Yorùbá'],
+            ['code' => 'vo', 'native_name' => 'Volapük'],
+            ['code' => 'wa', 'native_name' => 'Walon'],
+            ['code' => 'wo', 'native_name' => 'Wollof'],
+            ['code' => 'xh', 'native_name' => 'isiXhosa'],
+            ['code' => 'yi', 'native_name' => 'ייִדיש'],
+            ['code' => 'yo', 'native_name' => 'Yorùbá'],
             [
                 'code' => 'za',
-                'name' => 'Zhuang, Chuang',
                 'native_name' => 'Saɯ cueŋƅ, Saw cuengh',
             ],
             [
                 'code' => 'zh',
-                'name' => 'Chinese',
                 'native_name' => '中文 (Zhōngwén), 汉语, 漢語',
             ],
-            ['code' => 'zu', 'name' => 'Zulu', 'native_name' => 'isiZulu'],
+            ['code' => 'zu', 'native_name' => 'isiZulu'],
         ];
 
         $this->db
diff --git a/app/Database/Seeds/PlatformSeeder.php b/app/Database/Seeds/PlatformSeeder.php
index 274e1e609003a137ad547e36d6634d2564f24568..636213ab3df2cabd104185f20cfca447e94cbb67 100644
--- a/app/Database/Seeds/PlatformSeeder.php
+++ b/app/Database/Seeds/PlatformSeeder.php
@@ -24,14 +24,12 @@ class PlatformSeeder extends Seeder
                 'home_url' => 'https://www.apple.com/itunes/podcasts/',
                 'submit_url' =>
                     'https://podcastsconnect.apple.com/my-podcasts/new-feed',
-                'icon_filename' => 'apple-podcasts.svg',
             ],
             [
                 'name' => 'blubrry',
                 'label' => 'Blubrry',
                 'home_url' => 'https://www.blubrry.com/',
                 'submit_url' => 'https://www.blubrry.com/addpodcast.php',
-                'icon_filename' => 'blubrry.svg',
             ],
             [
                 'name' => 'castbox',
@@ -39,21 +37,18 @@ class PlatformSeeder extends Seeder
                 'home_url' => 'https://castbox.fm/',
                 'submit_url' =>
                     'https://helpcenter.castbox.fm/portal/kb/articles/submit-my-podcast',
-                'icon_filename' => 'castbox.svg',
             ],
             [
                 'name' => 'castro',
                 'label' => 'Castro',
                 'home_url' => 'http://castro.fm/',
                 'submit_url' => null,
-                'icon_filename' => 'castro.svg',
             ],
             [
                 'name' => 'deezer',
                 'label' => 'Deezer',
                 'home_url' => 'https://www.deezer.com/',
                 'submit_url' => 'https://podcasters.deezer.com/submission',
-                'icon_filename' => 'deezer.svg',
             ],
             [
                 'name' => 'google-podcasts',
@@ -61,98 +56,84 @@ class PlatformSeeder extends Seeder
                 'home_url' => 'https://podcasts.google.com/about',
                 'submit_url' =>
                     'https://search.google.com/search-console/about',
-                'icon_filename' => 'google-podcasts.svg',
             ],
             [
                 'name' => 'ivoox',
                 'label' => 'Ivoox',
                 'home_url' => 'https://www.ivoox.com/',
                 'submit_url' => null,
-                'icon_filename' => 'ivoox.svg',
             ],
             [
                 'name' => 'listennotes',
                 'label' => 'ListenNotes',
                 'home_url' => 'https://www.listennotes.com/',
                 'submit_url' => 'https://www.listennotes.com/submit/',
-                'icon_filename' => 'listennotes.svg',
             ],
             [
                 'name' => 'overcast',
                 'label' => 'Overcast',
                 'home_url' => 'https://overcast.fm/',
                 'submit_url' => 'https://overcast.fm/podcasterinfo',
-                'icon_filename' => 'overcast.svg',
             ],
             [
                 'name' => 'playerfm',
                 'label' => 'Player.Fm',
                 'home_url' => 'https://player.fm/',
                 'submit_url' => 'https://player.fm/importer/feed',
-                'icon_filename' => 'playerfm.svg',
             ],
             [
                 'name' => 'pocketcasts',
                 'label' => 'Pocketcasts',
                 'home_url' => 'https://www.pocketcasts.com/',
                 'submit_url' => 'https://www.pocketcasts.com/submit/',
-                'icon_filename' => 'pocketcasts.svg',
             ],
             [
                 'name' => 'podbean',
                 'label' => 'Podbean',
                 'home_url' => 'https://www.podbean.com/',
                 'submit_url' => 'https://www.podbean.com/site/submitPodcast',
-                'icon_filename' => 'podbean.svg',
             ],
             [
                 'name' => 'podcast-addict',
                 'label' => 'Podcast Addict',
                 'home_url' => 'https://podcastaddict.com/',
                 'submit_url' => 'https://podcastaddict.com/submit',
-                'icon_filename' => 'podcast-addict.svg',
             ],
             [
                 'name' => 'podchaser',
                 'label' => 'Podchaser',
                 'home_url' => 'https://www.podchaser.com/',
                 'submit_url' => 'https://www.podchaser.com/creators/edit',
-                'icon_filename' => 'podchaser.svg',
             ],
             [
                 'name' => 'podtail',
                 'label' => 'Podtail',
                 'home_url' => 'https://podtail.com/',
                 'submit_url' => 'https://podtail.com/about/faq/',
-                'icon_filename' => 'podtail.svg',
             ],
             [
                 'name' => 'radiopublic',
                 'label' => 'Radiopublic',
                 'home_url' => 'https://radiopublic.com/',
                 'submit_url' => 'https://podcasters.radiopublic.com/signup',
-                'icon_filename' => 'radiopublic.svg',
             ],
             [
                 'name' => 'spotify',
                 'label' => 'Spotify',
                 'home_url' => 'https://www.spotify.com/',
                 'submit_url' => 'https://podcasters.spotify.com/submit',
-                'icon_filename' => 'spotify.svg',
             ],
             [
                 'name' => 'spreaker',
                 'label' => 'Spreaker',
                 'home_url' => 'https://www.spreaker.com/',
                 'submit_url' => 'https://www.spreaker.com/cms/shows/rss-import',
-                'icon_filename' => 'spreaker.svg',
             ],
             [
                 'name' => 'stitcher',
                 'label' => 'Stitcher',
                 'home_url' => 'https://www.stitcher.com/',
                 'submit_url' => 'https://www.stitcher.com/content-providers',
-                'icon_filename' => 'stitcher.svg',
             ],
             [
                 'name' => 'tunein',
@@ -160,7 +141,6 @@ class PlatformSeeder extends Seeder
                 'home_url' => 'https://tunein.com/',
                 'submit_url' =>
                     'https://help.tunein.com/contact/add-podcast-S19TR3Sdf',
-                'icon_filename' => 'tunein.svg',
             ],
         ];
         $this->db
diff --git a/app/Entities/AnalyticsPodcasts.php b/app/Entities/AnalyticsPodcasts.php
index b15e94e367cf2455b92a2159eb89ef83780e1efd..b8e74b8f51f08dd1981e3adc376a022bbbfa3af4 100644
--- a/app/Entities/AnalyticsPodcasts.php
+++ b/app/Entities/AnalyticsPodcasts.php
@@ -17,7 +17,9 @@ class AnalyticsPodcasts extends Entity
     protected $casts = [
         'podcast_id' => 'integer',
         'date' => 'datetime',
-        'hits' => 'integer',
+        'duration' => 'integer',
+        'bandwidth' => 'integer',
         'unique_listeners' => 'integer',
+        'hits' => 'integer',
     ];
 }
diff --git a/app/Entities/AnalyticsPodcastsByHour.php b/app/Entities/AnalyticsPodcastsByHour.php
new file mode 100644
index 0000000000000000000000000000000000000000..32dde6f34731af34f90e11a52b26fbd8e2c7ad74
--- /dev/null
+++ b/app/Entities/AnalyticsPodcastsByHour.php
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * Class AnalyticsPodcastsByHour
+ * Entity for AnalyticsPodcastsByHour
+ * @copyright  2020 Podlibre
+ * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
+ * @link       https://castopod.org/
+ */
+
+namespace App\Entities;
+
+use CodeIgniter\Entity;
+
+class AnalyticsPodcastsByHour extends Entity
+{
+    protected $casts = [
+        'podcast_id' => 'integer',
+        'date' => 'datetime',
+        'hour' => 'integer',
+        'hits' => 'integer',
+    ];
+}
diff --git a/app/Entities/AnalyticsPodcastsByPlayer.php b/app/Entities/AnalyticsPodcastsByPlayer.php
index b0e19d26948fe5017458651d2eb0efdf6f118456..e19f8360bcc9f8bd26be4d6fc0186a4a27c2ed24 100644
--- a/app/Entities/AnalyticsPodcastsByPlayer.php
+++ b/app/Entities/AnalyticsPodcastsByPlayer.php
@@ -19,7 +19,7 @@ class AnalyticsPodcastsByPlayer extends Entity
         'app' => '?string',
         'device' => '?string',
         'os' => '?string',
-        'bot' => 'boolean',
+        'is_bot' => 'boolean',
         'date' => 'datetime',
         'hits' => 'integer',
     ];
diff --git a/app/Entities/AnalyticsWebsiteByEntryPage.php b/app/Entities/AnalyticsWebsiteByEntryPage.php
index 344d60fb2bc4dd136977c656d84b715a015c5a96..d12c9bdb0c80af7458036bd14f3722d1329a1163 100644
--- a/app/Entities/AnalyticsWebsiteByEntryPage.php
+++ b/app/Entities/AnalyticsWebsiteByEntryPage.php
@@ -16,7 +16,7 @@ class AnalyticsWebsiteByEntryPage extends Entity
 {
     protected $casts = [
         'podcast_id' => 'integer',
-        'entry_page' => '?string',
+        'entry_page_url' => 'string',
         'date' => 'datetime',
         'hits' => 'integer',
     ];
diff --git a/app/Entities/AnalyticsWebsiteByReferer.php b/app/Entities/AnalyticsWebsiteByReferer.php
index 959554f957b5a530d4c2628832e0965a869d9caa..30b0b2bffec397b5ef159049816a6fe88e42e8a2 100644
--- a/app/Entities/AnalyticsWebsiteByReferer.php
+++ b/app/Entities/AnalyticsWebsiteByReferer.php
@@ -16,7 +16,7 @@ class AnalyticsWebsiteByReferer extends Entity
 {
     protected $casts = [
         'podcast_id' => 'integer',
-        'referer' => 'string',
+        'referer_url' => 'string',
         'date' => 'datetime',
         'hits' => 'integer',
     ];
diff --git a/app/Entities/Episode.php b/app/Entities/Episode.php
index 05d213bbb3c98f4bf8b1393a7207e63c9b43e072..79c45a7ae2408aadfc79238cd5b18b6d2c428e6b 100644
--- a/app/Entities/Episode.php
+++ b/app/Entities/Episode.php
@@ -51,9 +51,11 @@ class Episode extends Entity
     protected $enclosure_web_url;
 
     /**
+     * Holds text only description, striped of any markdown or html special characters
+     *
      * @var string
      */
-    protected $description_html;
+    protected $description;
 
     /**
      * @var boolean
@@ -76,13 +78,14 @@ class Episode extends Entity
         'enclosure_mimetype' => 'string',
         'enclosure_filesize' => 'integer',
         'enclosure_headersize' => 'integer',
-        'description' => 'string',
+        'description_markdown' => 'string',
+        'description_html' => 'string',
         'image_uri' => '?string',
         'parental_advisory' => '?string',
         'number' => '?integer',
         'season_number' => '?integer',
         'type' => 'string',
-        'block' => 'boolean',
+        'is_blocked' => 'boolean',
         'created_by' => 'integer',
         'updated_by' => 'integer',
     ];
@@ -194,6 +197,7 @@ class Episode extends Entity
                                 60
                         ),
                 $this->attributes['enclosure_filesize'],
+                $this->attributes['enclosure_duration'],
                 $this->attributes['enclosure_uri']
             )
         );
@@ -229,23 +233,49 @@ class Episode extends Entity
         );
     }
 
-    public function getDescriptionHtml()
+    public function setDescriptionMarkdown(string $descriptionMarkdown)
     {
         $converter = new CommonMarkConverter([
             'html_input' => 'strip',
             'allow_unsafe_links' => false,
         ]);
 
+        $this->attributes['description_markdown'] = $descriptionMarkdown;
+        $this->attributes['description_html'] = $converter->convertToHtml(
+            $descriptionMarkdown
+        );
+
+        return $this;
+    }
+
+    public function getDescriptionHtml()
+    {
         if (
-            $descriptionFooter = $this->getPodcast()->episode_description_footer
+            $descriptionFooter = $this->getPodcast()
+                ->episode_description_footer_html
         ) {
-            return $converter->convertToHtml($this->attributes['description']) .
+            return $this->attributes['description_html'] .
                 '<footer>' .
-                $converter->convertToHtml($descriptionFooter) .
+                $descriptionFooter .
                 '</footer>';
         }
 
-        return $converter->convertToHtml($this->attributes['description']);
+        return $this->attributes['description_html'];
+    }
+
+    public function getDescription()
+    {
+        if ($this->description) {
+            return $this->description;
+        }
+
+        return trim(
+            preg_replace(
+                '/\s+/',
+                ' ',
+                strip_tags($this->attributes['description_html'])
+            )
+        );
     }
 
     public function setCreatedBy(\App\Entities\User $user)
diff --git a/app/Entities/Platform.php b/app/Entities/Platform.php
index cd51209e2347f586d21697439887da0dec9b8f16..7496900fed9bd5b352ccce4a82fb925b8fe7c2ac 100644
--- a/app/Entities/Platform.php
+++ b/app/Entities/Platform.php
@@ -19,6 +19,6 @@ class Platform extends Entity
         'home_url' => 'string',
         'submit_url' => '?string',
         'link_url' => '?string',
-        'visible' => '?boolean',
+        'is_visible' => '?boolean',
     ];
 }
diff --git a/app/Entities/Podcast.php b/app/Entities/Podcast.php
index e64cd5bca7318f9e32a76122023eb61377977965..258a425a197c23d8e304a80de5427aa2badf9b6b 100644
--- a/app/Entities/Podcast.php
+++ b/app/Entities/Podcast.php
@@ -53,33 +53,37 @@ class Podcast extends Entity
     protected $contributors;
 
     /**
-     * @var string
+     * @var \App\Entities\Platform
      */
-    protected $description_html;
+    protected $platforms;
 
     /**
-     * @var \App\Entities\Platform
+     * Holds text only description, striped of any markdown or html special characters
+     *
+     * @var string
      */
-    protected $platforms;
+    protected $description;
 
     protected $casts = [
         'id' => 'integer',
         'title' => 'string',
         'name' => 'string',
-        'description' => 'string',
+        'description_markdown' => 'string',
+        'description_html' => 'string',
         'image_uri' => 'string',
-        'language' => 'string',
+        'language_code' => 'string',
         'category_id' => 'integer',
         'parental_advisory' => '?string',
         'publisher' => '?string',
-        'owner_name' => '?string',
-        'owner_email' => '?string',
+        'owner_name' => 'string',
+        'owner_email' => 'string',
         'type' => 'string',
         'copyright' => '?string',
-        'episode_description_footer' => '?string',
-        'block' => 'boolean',
-        'complete' => 'boolean',
-        'lock' => 'boolean',
+        'episode_description_footer_markdown' => '?string',
+        'episode_description_footer_html' => '?string',
+        'is_blocked' => 'boolean',
+        'is_completed' => 'boolean',
+        'is_locked' => 'boolean',
         'imported_feed_url' => '?string',
         'new_feed_url' => '?string',
         'created_by' => 'integer',
@@ -191,14 +195,54 @@ class Podcast extends Entity
         return $this->contributors;
     }
 
-    public function getDescriptionHtml()
+    public function setDescriptionMarkdown(string $descriptionMarkdown)
     {
         $converter = new CommonMarkConverter([
             'html_input' => 'strip',
             'allow_unsafe_links' => false,
         ]);
 
-        return $converter->convertToHtml($this->attributes['description']);
+        $this->attributes['description_markdown'] = $descriptionMarkdown;
+        $this->attributes['description_html'] = $converter->convertToHtml(
+            $descriptionMarkdown
+        );
+
+        return $this;
+    }
+
+    public function setEpisodeDescriptionFooterMarkdown(
+        string $episodeDescriptionFooterMarkdown = null
+    ) {
+        if ($episodeDescriptionFooterMarkdown) {
+            $converter = new CommonMarkConverter([
+                'html_input' => 'strip',
+                'allow_unsafe_links' => false,
+            ]);
+
+            $this->attributes[
+                'episode_description_footer_markdown'
+            ] = $episodeDescriptionFooterMarkdown;
+            $this->attributes[
+                'episode_description_footer_html'
+            ] = $converter->convertToHtml($episodeDescriptionFooterMarkdown);
+        }
+
+        return $this;
+    }
+
+    public function getDescription()
+    {
+        if ($this->description) {
+            return $this->description;
+        }
+
+        return trim(
+            preg_replace(
+                '/\s+/',
+                ' ',
+                strip_tags($this->attributes['description_html'])
+            )
+        );
     }
 
     public function setCreatedBy(\App\Entities\User $user)
@@ -229,7 +273,7 @@ class Podcast extends Entity
         }
 
         if (empty($this->platforms)) {
-            $this->platforms = (new PlatformModel())->getPodcastPlatformLinks(
+            $this->platforms = (new PlatformModel())->getPodcastPlatforms(
                 $this->id
             );
         }
diff --git a/app/Helpers/analytics_helper.php b/app/Helpers/analytics_helper.php
index 1eef6ecce352a016ad9908ff19a12f6d9b96a1ca..998f94a32bac5ed378a553eba016a4d55f04736b 100644
--- a/app/Helpers/analytics_helper.php
+++ b/app/Helpers/analytics_helper.php
@@ -244,6 +244,7 @@ function podcast_hit(
     $episodeId,
     $bytesThreshold,
     $fileSize,
+    $duration,
     $serviceName
 ) {
     $session = \Config\Services::session();
@@ -335,20 +336,25 @@ function podcast_hit(
                 // We save the download count for this user until midnight:
                 cache()->save($listenerHashId, $downloadsByUser, $midnightTTL);
 
-                $db->query("CALL $procedureName(?,?,?,?,?,?,?,?,?,?,?,?);", [
-                    $podcastId,
-                    $episodeId,
-                    $session->get('location')['countryCode'],
-                    $session->get('location')['regionCode'],
-                    $session->get('location')['latitude'],
-                    $session->get('location')['longitude'],
-                    $serviceName,
-                    $session->get('player')['app'],
-                    $session->get('player')['device'],
-                    $session->get('player')['os'],
-                    $session->get('player')['bot'],
-                    $newListener,
-                ]);
+                $db->query(
+                    "CALL $procedureName(?,?,?,?,?,?,?,?,?,?,?,?,?,?);",
+                    [
+                        $podcastId,
+                        $episodeId,
+                        $session->get('location')['countryCode'],
+                        $session->get('location')['regionCode'],
+                        $session->get('location')['latitude'],
+                        $session->get('location')['longitude'],
+                        $serviceName,
+                        $session->get('player')['app'],
+                        $session->get('player')['device'],
+                        $session->get('player')['os'],
+                        $session->get('player')['bot'],
+                        $fileSize,
+                        $duration,
+                        $newListener,
+                    ]
+                );
             }
         }
     } catch (\Exception $e) {
diff --git a/app/Helpers/id3_helper.php b/app/Helpers/id3_helper.php
index 61c21e2e55d3f6c29fc83a078a5bc07444e30a94..2e7b18596908ebeeef4c1939639cd2782ff32bad 100644
--- a/app/Helpers/id3_helper.php
+++ b/app/Helpers/id3_helper.php
@@ -60,13 +60,17 @@ function write_enclosure_tags($episode)
     // populate data array
     $TagData = [
         'title' => [$episode->title],
-        'artist' => [$episode->podcast->author],
+        'artist' => [
+            empty($episode->podcast->publisher)
+                ? $episode->podcast->owner_name
+                : $episode->podcast->publisher,
+        ],
         'album' => [$episode->podcast->title],
         'year' => [
             $episode->published_at ? $episode->published_at->format('Y') : '',
         ],
         'genre' => ['Podcast'],
-        'comment' => [$episode->description],
+        'comment' => [$episode->description_html],
         'track_number' => [strval($episode->number)],
         'copyright_message' => [$episode->podcast->copyright],
         'publisher' => [
@@ -81,7 +85,7 @@ function write_enclosure_tags($episode)
         // 'podcast' => [],
         // 'podcast_identifier' => [$episode_media_url],
         // 'podcast_feed' => [$podcast_feed_url],
-        // 'podcast_description' => [$podcast->description],
+        // 'podcast_description' => [$podcast->description_markdown],
     ];
 
     $TagData['attached_picture'][] = [
diff --git a/app/Helpers/rss_helper.php b/app/Helpers/rss_helper.php
index 265841ce9b0c2d48425fff950b36480f5d09961f..93dbbdcefce6df5edb54d61e1dfad3915a85ac79 100644
--- a/app/Helpers/rss_helper.php
+++ b/app/Helpers/rss_helper.php
@@ -63,9 +63,13 @@ function get_rss_feed($podcast, $serviceName = '')
     $channel->addChildWithCDATA('description', $podcast->description_html);
     $itunes_image = $channel->addChild('image', null, $itunes_namespace);
     $itunes_image->addAttribute('href', $podcast->image->original_url);
-    $channel->addChild('language', $podcast->language);
+    $channel->addChild('language', $podcast->language_code);
     $channel
-        ->addChild('locked', $podcast->lock ? 'yes' : 'no', $podcast_namespace)
+        ->addChild(
+            'locked',
+            $podcast->is_locked ? 'yes' : 'no',
+            $podcast_namespace
+        )
         ->addAttribute('owner', $podcast->owner_email);
     // set main category first, then other categories as apple
     add_category_tag($channel, $podcast->category);
@@ -89,8 +93,9 @@ function get_rss_feed($podcast, $serviceName = '')
 
     $channel->addChild('type', $podcast->type, $itunes_namespace);
     $podcast->copyright && $channel->addChild('copyright', $podcast->copyright);
-    $podcast->block && $channel->addChild('block', 'Yes', $itunes_namespace);
-    $podcast->complete &&
+    $podcast->is_blocked &&
+        $channel->addChild('block', 'Yes', $itunes_namespace);
+    $podcast->is_completed &&
         $channel->addChild('complete', 'Yes', $itunes_namespace);
 
     $image = $channel->addChild('image');
@@ -146,7 +151,8 @@ function get_rss_feed($podcast, $serviceName = '')
             );
         $item->addChild('episodeType', $episode->type, $itunes_namespace);
 
-        $episode->block && $item->addChild('block', 'Yes', $itunes_namespace);
+        $episode->is_blocked &&
+            $item->addChild('block', 'Yes', $itunes_namespace);
     }
 
     return $rss->asXML();
diff --git a/app/Helpers/svg_helper.php b/app/Helpers/svg_helper.php
index 921284c9d6fea6088d9b8020e8038e8a517db08d..ba776527d09bca35f3019d6604cd2d3ea25b3213 100644
--- a/app/Helpers/svg_helper.php
+++ b/app/Helpers/svg_helper.php
@@ -57,7 +57,9 @@ function svg($name, $class = null)
 function platform_icon($name, $class = null)
 {
     try {
-        $svg_contents = file_get_contents('assets/images/platforms/' . $name);
+        $svg_contents = file_get_contents(
+            'assets/images/platforms/' . $name . '.svg'
+        );
     } catch (\Exception $e) {
         $svg_contents = file_get_contents(
             'assets/images/platforms/_default.svg'
diff --git a/app/Language/en/Podcast.php b/app/Language/en/Podcast.php
index d979ae78b5df0751875d303812373cb98c07c8fd..acf88d9f22b71a4f0a3ce886ee44cfa404c20440 100644
--- a/app/Language/en/Podcast.php
+++ b/app/Language/en/Podcast.php
@@ -65,7 +65,7 @@ return [
         'status_section_subtitle' => 'Dead or alive?',
         'block' => 'Podcast should be hidden from all platforms',
         'complete' => 'Podcast will not be having new episodes',
-        'lock' => 'Podcast is locked for export',
+        'lock' => 'Prevent podcast from being copied',
         'lock_hint' =>
             'The purpose is to tell other podcast platforms whether they are allowed to import this feed. A value of yes means that any attempt to import this feed into a new platform should be rejected.',
         'submit_create' => 'Create podcast',
diff --git a/app/Language/fr/Podcast.php b/app/Language/fr/Podcast.php
index 8fe3ad145de65c305f7f58f8a182251de58592da..117a8bb789dc0267e0313c39cb3e178268ad2a46 100644
--- a/app/Language/fr/Podcast.php
+++ b/app/Language/fr/Podcast.php
@@ -66,7 +66,7 @@ return [
         'status_section_subtitle' => 'Vivant ou mort ?',
         'block' => 'Le podcast doit être masqué sur toutes les plateformes',
         'complete' => 'Le podcast n’aura plus de nouveaux épisodes.',
-        'lock' => 'Le podcast est fermé à l’export',
+        'lock' => 'Empêcher la copie du podcast',
         'lock_hint' =>
             'Le but est d’indiquer aux autres plates-formes de podcast si elles sont autorisées à importer ce flux. La valeur « oui » signifie que toute tentative d’importation de ce flux dans une nouvelle plateforme doit être rejetée.',
         'submit_create' => 'Créer le podcast',
diff --git a/app/Models/AnalyticsPodcastByEpisodeModel.php b/app/Models/AnalyticsPodcastByEpisodeModel.php
index 29506bda7eadcd821162fa65313ce31858f0177a..fce1544546bf690aeecc7bec00ec1788b7355712 100644
--- a/app/Models/AnalyticsPodcastByEpisodeModel.php
+++ b/app/Models/AnalyticsPodcastByEpisodeModel.php
@@ -142,71 +142,4 @@ class AnalyticsPodcastByEpisodeModel extends Model
         }
         return $found;
     }
-
-    /**
-     * Gets listening-time data for a podcast
-     *
-     * @param int $podcastId
-     *
-     * @return array
-     */
-    public function getDataTotalListeningTimeByDay(int $podcastId): array
-    {
-        if (
-            !($found = cache(
-                "{$podcastId}_analytics_podcast_listening_time_by_day"
-            ))
-        ) {
-            $found = $this->select('date as labels')
-                ->selectSum('(enclosure_duration * hits)', 'values')
-                ->join('episodes', 'id = episode_id', 'inner')
-                ->where([
-                    $this->table . '.podcast_id' => $podcastId,
-                    'date >' => date('Y-m-d', strtotime('-60 days')),
-                ])
-                ->groupBy('labels')
-                ->orderBy('labels', 'ASC')
-                ->findAll();
-
-            cache()->save(
-                "{$podcastId}_analytics_podcast_listening_time_by_day",
-                $found,
-                600
-            );
-        }
-        return $found;
-    }
-
-    /**
-     * Gets listening-time data for a podcast
-     *
-     * @param int $podcastId
-     *
-     * @return array
-     */
-    public function getDataTotalListeningTimeByMonth(int $podcastId): array
-    {
-        if (
-            !($found = cache(
-                "{$podcastId}_analytics_podcast_listening_time_by_month"
-            ))
-        ) {
-            $found = $this->select('DATE_FORMAT(`date`,"%Y-%m-01") as `labels`')
-                ->selectSum('(enclosure_duration * hits)', 'values')
-                ->join('episodes', 'id = episode_id', 'inner')
-                ->where([
-                    $this->table . '.podcast_id' => $podcastId,
-                ])
-                ->groupBy('`labels`')
-                ->orderBy('`labels`', 'ASC')
-                ->findAll();
-
-            cache()->save(
-                "{$podcastId}_analytics_podcast_listening_time_by_month",
-                $found,
-                600
-            );
-        }
-        return $found;
-    }
 }
diff --git a/app/Models/AnalyticsPodcastByHourModel.php b/app/Models/AnalyticsPodcastByHourModel.php
new file mode 100644
index 0000000000000000000000000000000000000000..9dd82a4d1a12cc1a6a832f45f705245224979689
--- /dev/null
+++ b/app/Models/AnalyticsPodcastByHourModel.php
@@ -0,0 +1,25 @@
+<?php
+
+/**
+ * Class AnalyticsPodcastByHour
+ * Model for analytics_podcasts_by_hour table in database
+ * @copyright  2020 Podlibre
+ * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
+ * @link       https://castopod.org/
+ */
+
+namespace App\Models;
+
+use CodeIgniter\Model;
+
+class AnalyticsPodcastByHourModel extends Model
+{
+    protected $table = 'analytics_podcasts_by_hour';
+
+    protected $allowedFields = [];
+
+    protected $returnType = \App\Entities\AnalyticsPodcastsByHour::class;
+    protected $useSoftDeletes = false;
+
+    protected $useTimestamps = false;
+}
diff --git a/app/Models/AnalyticsPodcastByPlayerModel.php b/app/Models/AnalyticsPodcastByPlayerModel.php
index 1fb6b899b2b927dd041a73bfd27fd7d2da3263ec..32dc29d5afdf36847a69f210678dba50c9ebb593 100644
--- a/app/Models/AnalyticsPodcastByPlayerModel.php
+++ b/app/Models/AnalyticsPodcastByPlayerModel.php
@@ -42,7 +42,7 @@ class AnalyticsPodcastByPlayerModel extends Model
                 ->where([
                     '`podcast_id`' => $podcastId,
                     '`service` !=' => '',
-                    '`bot`' => 0,
+                    '`is_bot`' => 0,
                     '`date` >' => date('Y-m-d', strtotime('-1 week')),
                 ])
                 ->groupBy('`labels`')
@@ -77,7 +77,7 @@ class AnalyticsPodcastByPlayerModel extends Model
                 ->where([
                     '`podcast_id`' => $podcastId,
                     '`app` !=' => '',
-                    '`bot`' => 0,
+                    '`is_bot`' => 0,
                     '`date` >' => date('Y-m-d', strtotime('-1 week')),
                 ])
                 ->groupBy('`labels`')
@@ -112,7 +112,7 @@ class AnalyticsPodcastByPlayerModel extends Model
                 ->where([
                     '`podcast_id`' => $podcastId,
                     '`app` !=' => '',
-                    '`bot`' => 0,
+                    '`is_bot`' => 0,
                     '`date` >' => date('Y-m-d', strtotime('-1 year')),
                 ])
                 ->groupBy('`labels`')
@@ -148,7 +148,7 @@ class AnalyticsPodcastByPlayerModel extends Model
                     '`podcast_id`' => $podcastId,
                     '`app` !=' => '',
                     '`os` !=' => '',
-                    '`bot`' => 0,
+                    '`is_bot`' => 0,
                     '`date` >' => date('Y-m-d', strtotime('-1 week')),
                 ])
                 ->groupBy('`labels`')
@@ -183,7 +183,7 @@ class AnalyticsPodcastByPlayerModel extends Model
                 ->where([
                     '`podcast_id`' => $podcastId,
                     '`device` !=' => '',
-                    '`bot`' => 0,
+                    '`is_bot`' => 0,
                     '`date` >' => date('Y-m-d', strtotime('-1 week')),
                 ])
                 ->groupBy('`labels`')
@@ -215,7 +215,7 @@ class AnalyticsPodcastByPlayerModel extends Model
                 ->selectSum('`hits`', '`values`')
                 ->where([
                     '`podcast_id`' => $podcastId,
-                    '`bot`' => 1,
+                    '`is_bot`' => 1,
                     '`date` >' => date('Y-m-d', strtotime('-1 year')),
                 ])
                 ->groupBy('`labels`')
diff --git a/app/Models/AnalyticsPodcastModel.php b/app/Models/AnalyticsPodcastModel.php
index 04518027a7d07f32da04b77569f32df39874bd41..e2c60ff583c0271cc841991c956df24e6bb71c6b 100644
--- a/app/Models/AnalyticsPodcastModel.php
+++ b/app/Models/AnalyticsPodcastModel.php
@@ -138,4 +138,69 @@ class AnalyticsPodcastModel extends Model
         }
         return $found;
     }
+
+    /**
+     * Gets listening-time data for a podcast
+     *
+     * @param int $podcastId
+     *
+     * @return array
+     */
+    public function getDataTotalListeningTimeByDay(int $podcastId): array
+    {
+        if (
+            !($found = cache(
+                "{$podcastId}_analytics_podcast_listening_time_by_day"
+            ))
+        ) {
+            $found = $this->select('date as labels')
+                ->selectSum('duration', 'values')
+                ->where([
+                    $this->table . '.podcast_id' => $podcastId,
+                    'date >' => date('Y-m-d', strtotime('-60 days')),
+                ])
+                ->groupBy('labels')
+                ->orderBy('labels', 'ASC')
+                ->findAll();
+
+            cache()->save(
+                "{$podcastId}_analytics_podcast_listening_time_by_day",
+                $found,
+                600
+            );
+        }
+        return $found;
+    }
+
+    /**
+     * Gets listening-time data for a podcast
+     *
+     * @param int $podcastId
+     *
+     * @return array
+     */
+    public function getDataTotalListeningTimeByMonth(int $podcastId): array
+    {
+        if (
+            !($found = cache(
+                "{$podcastId}_analytics_podcast_listening_time_by_month"
+            ))
+        ) {
+            $found = $this->select('DATE_FORMAT(`date`,"%Y-%m-01") as `labels`')
+                ->selectSum('duration', 'values')
+                ->where([
+                    $this->table . '.podcast_id' => $podcastId,
+                ])
+                ->groupBy('`labels`')
+                ->orderBy('`labels`', 'ASC')
+                ->findAll();
+
+            cache()->save(
+                "{$podcastId}_analytics_podcast_listening_time_by_month",
+                $found,
+                600
+            );
+        }
+        return $found;
+    }
 }
diff --git a/app/Models/AnalyticsWebsiteByEntryPageModel.php b/app/Models/AnalyticsWebsiteByEntryPageModel.php
index 179f4d57e8442c48a01c68405d3ef71588ecf84c..4365a9de41014e73f9ae623c3f3b345d1319eac3 100644
--- a/app/Models/AnalyticsWebsiteByEntryPageModel.php
+++ b/app/Models/AnalyticsWebsiteByEntryPageModel.php
@@ -34,7 +34,7 @@ class AnalyticsWebsiteByEntryPageModel extends Model
     {
         if (!($found = cache("{$podcastId}_analytics_website_by_entry_page"))) {
             $found = $this->select(
-                'IF(`entry_page`=\'/\',\'/\',SUBSTRING_INDEX(`entry_page`,\'/\',-1)) as `labels`'
+                'IF(`entry_page_url`=\'/\',\'/\',SUBSTRING_INDEX(`entry_page_url`,\'/\',-1)) as `labels`'
             )
                 ->selectSum('`hits`', '`values`')
                 ->where([
diff --git a/app/Models/AnalyticsWebsiteByRefererModel.php b/app/Models/AnalyticsWebsiteByRefererModel.php
index b7805b94f1a407b12e3962fa4393d03b03d6009a..045b85142ab4c65b21b160de9002420e35f5b114 100644
--- a/app/Models/AnalyticsWebsiteByRefererModel.php
+++ b/app/Models/AnalyticsWebsiteByRefererModel.php
@@ -33,7 +33,7 @@ class AnalyticsWebsiteByRefererModel extends Model
     public function getData(int $podcastId): array
     {
         if (!($found = cache("{$podcastId}_analytics_website_by_referer"))) {
-            $found = $this->select('`referer` as `labels`')
+            $found = $this->select('`referer_url` as `labels`')
                 ->selectSum('`hits`', '`values`')
                 ->where([
                     '`podcast_id`' => $podcastId,
diff --git a/app/Models/EpisodeModel.php b/app/Models/EpisodeModel.php
index e01d5e35ca126707ddb79f237844357a95b20bd4..9ce7ce0cf29e0a4ee6ddc635452dbdca57b0cb59 100644
--- a/app/Models/EpisodeModel.php
+++ b/app/Models/EpisodeModel.php
@@ -25,13 +25,14 @@ class EpisodeModel extends Model
         'enclosure_mimetype',
         'enclosure_filesize',
         'enclosure_headersize',
-        'description',
+        'description_markdown',
+        'description_html',
         'image_uri',
         'parental_advisory',
         'number',
         'season_number',
         'type',
-        'block',
+        'is_blocked',
         'published_at',
         'created_by',
         'updated_by',
@@ -47,7 +48,7 @@ class EpisodeModel extends Model
         'title' => 'required',
         'slug' => 'required|regex_match[/^[a-zA-Z0-9\-]{1,191}$/]',
         'enclosure_uri' => 'required',
-        'description' => 'required',
+        'description_markdown' => 'required',
         'number' => 'is_natural_no_zero|permit_empty',
         'season_number' => 'is_natural_no_zero|permit_empty',
         'type' => 'required',
diff --git a/app/Models/PlatformModel.php b/app/Models/PlatformModel.php
index abba0a525f2f12fb0280f8cd0b01a1734de9c8e8..684135ac924c0221da12cfc67656b52f0aa63a44 100644
--- a/app/Models/PlatformModel.php
+++ b/app/Models/PlatformModel.php
@@ -18,18 +18,7 @@ class PlatformModel extends Model
     protected $table = 'platforms';
     protected $primaryKey = 'id';
 
-    protected $allowedFields = [
-        'name',
-        'home_url',
-        'submit_url',
-        'iosapp_url',
-        'androidapp_url',
-        'comment',
-        'display_by_default',
-        'ios_deeplink',
-        'android_deeplink',
-        'logo_file_name',
-    ];
+    protected $allowedFields = ['name', 'label', 'home_url', 'submit_url'];
 
     protected $returnType = \App\Entities\Platform::class;
     protected $useSoftDeletes = false;
@@ -40,7 +29,7 @@ class PlatformModel extends Model
     {
         if (!($found = cache("podcast{$podcastId}_platforms"))) {
             $found = $this->select(
-                'platforms.*, platform_links.link_url, platform_links.visible'
+                'platforms.*, platform_links.link_url, platform_links.is_visible'
             )
                 ->join(
                     'platform_links',
@@ -55,11 +44,11 @@ class PlatformModel extends Model
         return $found;
     }
 
-    public function getPodcastPlatformLinks($podcastId)
+    public function getPodcastPlatforms($podcastId)
     {
-        if (!($found = cache("podcast{$podcastId}_platformLinks"))) {
+        if (!($found = cache("podcast{$podcastId}_podcastPlatforms"))) {
             $found = $this->select(
-                'platforms.*, platform_links.link_url, platform_links.visible'
+                'platforms.*, platform_links.link_url, platform_links.is_visible'
             )
                 ->join(
                     'platform_links',
@@ -68,13 +57,17 @@ class PlatformModel extends Model
                 ->where('platform_links.podcast_id', $podcastId)
                 ->findAll();
 
-            cache()->save("podcast{$podcastId}_platformLinks", $found, DECADE);
+            cache()->save(
+                "podcast{$podcastId}_podcastPlatforms",
+                $found,
+                DECADE
+            );
         }
 
         return $found;
     }
 
-    public function savePlatformLinks($podcastId, $platformLinksData)
+    public function savePodcastPlatforms($podcastId, $platformLinksData)
     {
         $this->clearCache($podcastId);
 
@@ -83,22 +76,18 @@ class PlatformModel extends Model
             ->table('platform_links')
             ->delete(['podcast_id' => $podcastId]);
 
-        // Set platformLinks
+        // Set podcastPlatforms
         return $this->db
             ->table('platform_links')
             ->insertBatch($platformLinksData);
     }
 
-    public function getPlatformId($platform)
+    public function getPlatformId(string $platformName)
     {
-        if (is_numeric($platform)) {
-            return (int) $platform;
-        }
-
-        $p = $this->where('name', $platform)->first();
+        $p = $this->where('name', $platformName)->first();
 
         if (!$p) {
-            $this->error = lang('Platform.platformNotFound', [$platform]);
+            $this->error = lang('Platform.platformNotFound', [$platformName]);
 
             return false;
         }
@@ -106,7 +95,7 @@ class PlatformModel extends Model
         return (int) $p->id;
     }
 
-    public function removePlatformLink($podcastId, $platformId)
+    public function removePodcastPlatform($podcastId, $platformId)
     {
         $this->clearCache($podcastId);
 
@@ -119,7 +108,7 @@ class PlatformModel extends Model
     public function clearCache($podcastId)
     {
         cache()->delete("podcast{$podcastId}_platforms");
-        cache()->delete("podcast{$podcastId}_platformLinks");
+        cache()->delete("podcast{$podcastId}_podcastPlatforms");
 
         // delete localized podcast page cache
         $episodeModel = new EpisodeModel();
diff --git a/app/Models/PodcastModel.php b/app/Models/PodcastModel.php
index 0cc21617f129d8489fb8e739f49555de5c13833f..1ac4531d73474aa8d101dfe4eb6832d07e5c496b 100644
--- a/app/Models/PodcastModel.php
+++ b/app/Models/PodcastModel.php
@@ -19,10 +19,12 @@ class PodcastModel extends Model
         'id',
         'title',
         'name',
-        'description',
-        'episode_description_footer',
+        'description_markdown',
+        'description_html',
+        'episode_description_footer_markdown',
+        'episode_description_footer_html',
         'image_uri',
-        'language',
+        'language_code',
         'category_id',
         'parental_advisory',
         'owner_name',
@@ -30,13 +32,13 @@ class PodcastModel extends Model
         'publisher',
         'type',
         'copyright',
-        'block',
-        'complete',
-        'lock',
-        'created_by',
-        'updated_by',
         'imported_feed_url',
         'new_feed_url',
+        'is_blocked',
+        'is_completed',
+        'is_locked',
+        'created_by',
+        'updated_by',
     ];
 
     protected $returnType = \App\Entities\Podcast::class;
@@ -48,9 +50,9 @@ class PodcastModel extends Model
         'title' => 'required',
         'name' =>
             'required|regex_match[/^[a-zA-Z0-9\_]{1,191}$/]|is_unique[podcasts.name,id,{id}]',
-        'description' => 'required',
+        'description_markdown' => 'required',
         'image_uri' => 'required',
-        'language' => 'required',
+        'language_code' => 'required',
         'category_id' => 'required',
         'owner_email' => 'required|valid_email',
         'type' => 'required',
@@ -97,10 +99,10 @@ class PodcastModel extends Model
         if (!($found = cache("user{$userId}_podcasts"))) {
             $found = $this->select('podcasts.*')
                 ->join(
-                    'users_podcasts',
-                    'users_podcasts.podcast_id = podcasts.id'
+                    'podcasts_users',
+                    'podcasts_users.podcast_id = podcasts.id'
                 )
-                ->where('users_podcasts.user_id', $userId)
+                ->where('podcasts_users.user_id', $userId)
                 ->findAll();
 
             cache()->save("user{$userId}_podcasts", $found, DECADE);
@@ -119,7 +121,7 @@ class PodcastModel extends Model
             'group_id' => (int) $groupId,
         ];
 
-        return $this->db->table('users_podcasts')->insert($data);
+        return $this->db->table('podcasts_users')->insert($data);
     }
 
     public function updatePodcastContributor($userId, $podcastId, $groupId)
@@ -127,7 +129,7 @@ class PodcastModel extends Model
         cache()->delete("podcast{$podcastId}_contributors");
 
         return $this->db
-            ->table('users_podcasts')
+            ->table('podcasts_users')
             ->where([
                 'user_id' => (int) $userId,
                 'podcast_id' => (int) $podcastId,
@@ -140,7 +142,7 @@ class PodcastModel extends Model
         cache()->delete("podcast{$podcastId}_contributors");
 
         return $this->db
-            ->table('users_podcasts')
+            ->table('podcasts_users')
             ->where([
                 'user_id' => $userId,
                 'podcast_id' => $podcastId,
@@ -151,7 +153,7 @@ class PodcastModel extends Model
     public function getContributorGroupId($userId, $podcastId)
     {
         $user_podcast = $this->db
-            ->table('users_podcasts')
+            ->table('podcasts_users')
             ->select('group_id')
             ->where([
                 'user_id' => $userId,
diff --git a/app/Models/UserModel.php b/app/Models/UserModel.php
index 3e0d942a268a1b1cafc75a72103989cf61f4a3ab..af71d7a15a4b5ad65feba2c3ea4beb15a1108fd3 100644
--- a/app/Models/UserModel.php
+++ b/app/Models/UserModel.php
@@ -16,12 +16,12 @@ class UserModel extends \Myth\Auth\Models\UserModel
     {
         if (!($found = cache("podcast{$podcastId}_contributors"))) {
             $found = $this->select('users.*, auth_groups.name as podcast_role')
-                ->join('users_podcasts', 'users_podcasts.user_id = users.id')
+                ->join('podcasts_users', 'podcasts_users.user_id = users.id')
                 ->join(
                     'auth_groups',
-                    'auth_groups.id = users_podcasts.group_id'
+                    'auth_groups.id = podcasts_users.group_id'
                 )
-                ->where('users_podcasts.podcast_id', $podcastId)
+                ->where('podcasts_users.podcast_id', $podcastId)
                 ->findAll();
 
             cache()->save("podcast{$podcastId}_contributors", $found, DECADE);
@@ -33,10 +33,10 @@ class UserModel extends \Myth\Auth\Models\UserModel
     public function getPodcastContributor($user_id, $podcast_id)
     {
         return $this->select(
-            'users.*, users_podcasts.podcast_id as podcast_id, auth_groups.name as podcast_role'
+            'users.*, podcasts_users.podcast_id as podcast_id, auth_groups.name as podcast_role'
         )
-            ->join('users_podcasts', 'users_podcasts.user_id = users.id')
-            ->join('auth_groups', 'auth_groups.id = users_podcasts.group_id')
+            ->join('podcasts_users', 'podcasts_users.user_id = users.id')
+            ->join('auth_groups', 'auth_groups.id = podcasts_users.group_id')
             ->where([
                 'users.id' => $user_id,
                 'podcast_id' => $podcast_id,
diff --git a/app/Views/admin/episode/create.php b/app/Views/admin/episode/create.php
index e72961cac3a39fce832f41607121890f7623487b..a948b1fa088b89b75fe5396e17d1ec9a4de7cdd6 100644
--- a/app/Views/admin/episode/create.php
+++ b/app/Views/admin/episode/create.php
@@ -179,7 +179,7 @@
         ],
         old(
             'description_footer',
-            $podcast->episode_description_footer ?? '',
+            $podcast->episode_description_footer_markdown ?? '',
             false
         ),
         'data-editor="markdown"'
diff --git a/app/Views/admin/episode/edit.php b/app/Views/admin/episode/edit.php
index cbce3925ab6bb7e66f3ee72e00452e3ff18079ae..b2f9382faa078cfe25cf99d87248ff2ecdbe7ce0 100644
--- a/app/Views/admin/episode/edit.php
+++ b/app/Views/admin/episode/edit.php
@@ -163,7 +163,7 @@
             'class' => 'form-textarea',
             'required' => 'required',
         ],
-        old('description', $episode->description, false),
+        old('description', $episode->description_markdown, false),
         'data-editor="markdown"'
     ) ?>
 </div>
@@ -183,7 +183,7 @@
         ],
         old(
             'description_footer',
-            $podcast->episode_description_footer ?? '',
+            $podcast->episode_description_footer_markdown ?? '',
             false
         ),
         'data-editor="markdown"'
@@ -269,10 +269,9 @@
 <?= form_switch(
     lang('Episode.form.block') .
         hint_tooltip(lang('Episode.form.block_hint'), 'ml-1'),
-
     ['id' => 'block', 'name' => 'block'],
     'yes',
-    old('block', $episode->block)
+    old('block', $episode->is_blocked)
 ) ?>
 
 <?= form_section_close() ?>
diff --git a/app/Views/admin/podcast/analytics/listening-time.php b/app/Views/admin/podcast/analytics/listening_time.php
similarity index 95%
rename from app/Views/admin/podcast/analytics/listening-time.php
rename to app/Views/admin/podcast/analytics/listening_time.php
index f6cd05d0a26e828235db4f50f6ede82c6836ce4e..2285f3761c67dfd42f8901b261cdfefff7b25949 100644
--- a/app/Views/admin/podcast/analytics/listening-time.php
+++ b/app/Views/admin/podcast/analytics/listening_time.php
@@ -15,7 +15,7 @@
 <div class="chart-xy" id="by-day-listening-time-graph" data-chart-type="xy-duration-chart" data-chart-url="<?= route_to(
     'analytics-data',
     $podcast->id,
-    'PodcastByEpisode',
+    'Podcast',
     'TotalListeningTimeByDay'
 ) ?>"></div>
 </div>
@@ -25,7 +25,7 @@
 <div class="chart-xy" id="by-month-listening-time-graph" data-chart-type="xy-duration-chart" data-chart-url="<?= route_to(
     'analytics-data',
     $podcast->id,
-    'PodcastByEpisode',
+    'Podcast',
     'TotalListeningTimeByMonth'
 ) ?>"></div>
 </div>
diff --git a/app/Views/admin/podcast/create.php b/app/Views/admin/podcast/create.php
index 09b2aa08c8b8690254a957a9a72442d42ee411d4..0196b6fb0ea3b7386d47d6085db937aa42e65ca5 100644
--- a/app/Views/admin/podcast/create.php
+++ b/app/Views/admin/podcast/create.php
@@ -27,7 +27,6 @@
     'id' => 'image',
     'name' => 'image',
     'class' => 'form-input',
-
     'required' => 'required',
     'type' => 'file',
     'accept' => '.jpg,.jpeg,.png',
@@ -59,27 +58,21 @@
     'required' => 'required',
 ]) ?>
 
-<?= form_fieldset('', ['class' => 'mb-4']) ?>
+<?= form_fieldset('', [
+    'class' => 'mb-4',
+]) ?>
     <legend>
     <?= lang('Podcast.form.type.label') .
         hint_tooltip(lang('Podcast.form.type.hint'), 'ml-1') ?>
     </legend>
     <?= form_radio(
-        [
-            'id' => 'episodic',
-            'name' => 'type',
-            'class' => 'form-radio-btn',
-        ],
+        ['id' => 'episodic', 'name' => 'type', 'class' => 'form-radio-btn'],
         'episodic',
         old('type') ? old('type') == 'episodic' : true
     ) ?>
     <label for="episodic"><?= lang('Podcast.form.type.episodic') ?></label>
     <?= form_radio(
-        [
-            'id' => 'serial',
-            'name' => 'type',
-            'class' => 'form-radio-btn',
-        ],
+        ['id' => 'serial', 'name' => 'type', 'class' => 'form-radio-btn'],
         'serial',
         old('type') ? old('type') == 'serial' : false
     ) ?>
@@ -238,14 +231,7 @@
     'value' => old('publisher'),
 ]) ?>
 
-<?= form_label(
-    lang('Podcast.form.copyright'),
-    'copyright',
-    [],
-
-    '',
-    true
-) ?>
+<?= form_label(lang('Podcast.form.copyright'), 'copyright', [], '', true) ?>
 <?= form_input([
     'id' => 'copyright',
     'name' => 'copyright',
@@ -263,22 +249,29 @@
 
 <?= form_switch(
     lang('Podcast.form.block'),
-    ['id' => 'block', 'name' => 'block'],
+    [
+        'id' => 'block',
+        'name' => 'block',
+    ],
     'yes',
     old('block', false),
-
     'mb-2'
 ) ?>
 
 <?= form_switch(
     lang('Podcast.form.complete'),
-    ['id' => 'complete', 'name' => 'complete'],
+    [
+        'id' => 'complete',
+        'name' => 'complete',
+    ],
     'yes',
-    old('complete', false)
+    old('complete', false),
+    'mb-2'
 ) ?>
 
 <?= form_switch(
-    lang('Podcast.form.lock'),
+    lang('Podcast.form.lock') .
+        hint_tooltip(lang('Podcast.form.lock_hint'), 'ml-1'),
     ['id' => 'lock', 'name' => 'lock'],
     'yes',
     old('lock', true)
diff --git a/app/Views/admin/podcast/edit.php b/app/Views/admin/podcast/edit.php
index b2c0286926af90c8a5df012a93b7d29df0c9253e..664bfd05afc014c9b5bdaba3222260f2c97ccd9e 100644
--- a/app/Views/admin/podcast/edit.php
+++ b/app/Views/admin/podcast/edit.php
@@ -88,7 +88,7 @@
             'class' => 'form-textarea',
             'required' => 'required',
         ],
-        old('description', $podcast->description, false),
+        old('description', $podcast->description_markdown, false),
         'data-editor="markdown"'
     ) ?>
 </div>
@@ -105,7 +105,7 @@
 <?= form_dropdown(
     'language',
     $languageOptions,
-    old('language', $podcast->language),
+    old('language', $podcast->language_code),
     [
         'id' => 'language',
         'class' => 'form-select mb-4',
@@ -261,7 +261,7 @@
     lang('Podcast.form.block'),
     ['id' => 'block', 'name' => 'block'],
     'yes',
-    old('block', $podcast->block),
+    old('block', $podcast->is_blocked),
     'mb-2'
 ) ?>
 
@@ -269,7 +269,7 @@
     lang('Podcast.form.complete'),
     ['id' => 'complete', 'name' => 'complete'],
     'yes',
-    old('complete', $podcast->complete),
+    old('complete', $podcast->is_completed),
     'mb-2'
 ) ?>
 
@@ -278,7 +278,7 @@
         hint_tooltip(lang('Podcast.form.lock_hint'), 'ml-1'),
     ['id' => 'lock', 'name' => 'lock'],
     'yes',
-    old('lock', $podcast->lock)
+    old('lock', $podcast->is_locked)
 ) ?>
 
 <?= form_section_close() ?>
diff --git a/app/Views/admin/podcast/settings/platforms.php b/app/Views/admin/podcast/settings/platforms.php
index ac75df8b957ae3c5cef61c4e8b4a61233711a9da..7daf991afbfdfde5d835827681aee5b701010f65 100644
--- a/app/Views/admin/podcast/settings/platforms.php
+++ b/app/Views/admin/podcast/settings/platforms.php
@@ -19,7 +19,7 @@
 
 <div class="relative flex items-start mb-4">
     <div class="flex flex-col w-12 mr-4">
-        <?= platform_icon($platform->icon_filename, 'w-full mb-1') ?>
+        <?= platform_icon($platform->name, 'w-full mb-1') ?>
         <div class="inline-flex bg-gray-200">
             <?= anchor($platform->home_url, icon('external-link', 'mx-auto'), [
                 'class' => 'flex-1 text-gray-600 hover:text-gray-900',
@@ -81,7 +81,7 @@
             'yes',
             old(
                 $platform->name . '_visible',
-                $platform->visible ? $platform->visible : false
+                $platform->is_visible ? $platform->is_visible : false
             ),
             'text-sm'
         ) ?>
diff --git a/app/Views/episode.php b/app/Views/episode.php
index 4e52bca255d64d1dbffa6a7508c479fa3f011825..2bebb296d99fd19f619019f38dd365a0635e2ddf 100644
--- a/app/Views/episode.php
+++ b/app/Views/episode.php
@@ -5,9 +5,7 @@
 <head>
     <meta charset="UTF-8"/>
     <title><?= $episode->title ?></title>
-    <meta name="description" content="<?= trim(
-        preg_replace('/\s+/', ' ', strip_tags($episode->description_html))
-    ) ?>"/>
+    <meta name="description" content="<?= $episode->description ?>"/>
     <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
     <link rel="shortcut icon" type="image/png" href="/favicon.ico" />
     <link rel="stylesheet" href="/assets/index.css"/>
diff --git a/app/Views/podcast.php b/app/Views/podcast.php
index 52329cd3535d6a4394d2275028ae535a6870f922..2d02c189bf13ae7a517d219451b5e3fd3810429a 100644
--- a/app/Views/podcast.php
+++ b/app/Views/podcast.php
@@ -6,9 +6,7 @@
 <head>
     <meta charset="UTF-8"/>
     <title><?= $podcast->title ?></title>
-    <meta name="description" content="<?= trim(
-        preg_replace('/\s+/', ' ', strip_tags($podcast->description_html))
-    ) ?>"/>
+    <meta name="description" content="<?= $podcast->description ?>"/>
     <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
     <link rel="shortcut icon" type="image/png" href="/favicon.ico" />
     <link rel="stylesheet" href="/assets/index.css"/>
@@ -46,12 +44,9 @@
                             ]
                         ) ?>
                     <?php foreach ($podcast->platforms as $platform): ?>
-                        <?php if ($platform->visible): ?>
+                        <?php if ($platform->is_visible): ?>
                             <a href="<?= $platform->link_url ?>" title="<?= $platform->label ?>" target="_blank" rel="noopener noreferrer" class="ml-2">
-                            <?= platform_icon(
-                                $platform->icon_filename,
-                                'h-8'
-                            ) ?>
+                            <?= platform_icon($platform->name, 'h-8') ?>
                             </a>
                         <?php endif; ?>
                     <?php endforeach; ?>
diff --git a/prepare-release.sh b/prepare-release.sh
index 93d53ae77dd2e7383c892c18636fa445381de504..ee392c12726534b1eeba6b5f44391d94976d9593 100644
--- a/prepare-release.sh
+++ b/prepare-release.sh
@@ -10,7 +10,7 @@ echo "$( jq '.version = "'$COMPOSER_VERSION'"' composer.json )" > composer.json
 sed -i "s/^defined('CP_VERSION').*/defined('CP_VERSION') || define('CP_VERSION', '$VERSION');/" ./app/Config/Constants.php
 
 # download GeoLite2-City archive and extract it to writable/uploads
-wget -c "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=v3PguJMcmZMb9Ld0&suffix=tar.gz" -O - | tar -xz -C ./writable/uploads/
+wget -c "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=$MAXMIND_LICENCE_KEY&suffix=tar.gz" -O - | tar -xz -C ./writable/uploads/
 
 # rename extracted archives' folders
 mv ./writable/uploads/GeoLite2-City* ./writable/uploads/GeoLite2-City