diff --git a/CHANGELOG.md b/CHANGELOG.md
index 25883d76efa59be8cc42b5efc9873024ae87de29..89c4882740150b3bdff53bde610305405b171610 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -44,6 +44,7 @@ If the tracker is not initialised correctly, the browser console will display th
 * The creation of settings has slightly changed to improve performance. It is now possible to create new settings via the method `$this->makeSetting()` see `Piwik\Plugins\ExampleSettingsPlugin\SystemSettings` for an example.
 * It is no longer possible to define an introduction text for settings.
 * If requesting multipe periods for one report, the keys that define the range are no longer translated. For example before 3.0 an API response may contain: `<result date="From 2010-02-01 to 2010-02-07">` which is now `<result date="2010-02-01,2010-02-07">`.
+* The method `Piwik\Plugin\Archiver::shouldRunEvenWhenNoVisits()` has been added. By overwriting this method and returning true, a plugin archiver can force the archiving to run even when there was no visit for the website/date/period/segment combination (by default, archivers are skipped when there is no visit).
 * The following deprecated events have been removed as mentioned.
  * `Tracker.existingVisitInformation` Use [dimensions](http://developer.piwik.org/guides/dimensions) instead of using `Tracker` events.
  * `Tracker.newVisitorInformation`
diff --git a/core/ArchiveProcessor/Loader.php b/core/ArchiveProcessor/Loader.php
index c08bf2c52cc26e45cd10e73b3a4c6a814736623d..e6c5015aabb3e51d299eb493fcfed6e2d0c9c14e 100644
--- a/core/ArchiveProcessor/Loader.php
+++ b/core/ArchiveProcessor/Loader.php
@@ -73,7 +73,7 @@ class Loader
         list($visits, $visitsConverted) = $this->prepareCoreMetricsArchive($visits, $visitsConverted);
         list($idArchive, $visits) = $this->prepareAllPluginsArchive($visits, $visitsConverted);
 
-        if ($this->isThereSomeVisits($visits)) {
+        if ($this->isThereSomeVisits($visits) || PluginsArchiver::doesAnyPluginArchiveWithoutVisits()) {
             return $idArchive;
         }
         return false;
@@ -120,11 +120,8 @@ class Loader
             $visitsConverted = $metrics['nb_visits_converted'];
         }
 
-        if ($this->isThereSomeVisits($visits)
-            || $this->shouldArchiveForSiteEvenWhenNoVisits()
-        ) {
-            $pluginsArchiver->callAggregateAllPlugins($visits, $visitsConverted);
-        }
+        $forceArchivingWithoutVisits = !$this->isThereSomeVisits($visits) && $this->shouldArchiveForSiteEvenWhenNoVisits();
+        $pluginsArchiver->callAggregateAllPlugins($visits, $visitsConverted, $forceArchivingWithoutVisits);
 
         $idArchive = $pluginsArchiver->finalizeArchive();
 
diff --git a/core/ArchiveProcessor/PluginsArchiver.php b/core/ArchiveProcessor/PluginsArchiver.php
index 325b529aa37f68147b0858a94e11288ef90709f9..42b497c4b74d4f150bb118f0d083365d360176ac 100644
--- a/core/ArchiveProcessor/PluginsArchiver.php
+++ b/core/ArchiveProcessor/PluginsArchiver.php
@@ -94,14 +94,14 @@ class PluginsArchiver
      * Instantiates the Archiver class in each plugin that defines it,
      * and triggers Aggregation processing on these plugins.
      */
-    public function callAggregateAllPlugins($visits, $visitsConverted)
+    public function callAggregateAllPlugins($visits, $visitsConverted, $forceArchivingWithoutVisits = false)
     {
         Log::debug("PluginsArchiver::%s: Initializing archiving process for all plugins [visits = %s, visits converted = %s]",
             __FUNCTION__, $visits, $visitsConverted);
 
         $this->archiveProcessor->setNumberOfVisits($visits, $visitsConverted);
 
-        $archivers = $this->getPluginArchivers();
+        $archivers = static::getPluginArchivers();
 
         foreach ($archivers as $pluginName => $archiverClass) {
             // We clean up below all tables created during this function call (and recursive calls)
@@ -111,7 +111,12 @@ class PluginsArchiver
             $archiver = $this->makeNewArchiverObject($archiverClass, $pluginName);
 
             if (!$archiver->isEnabled()) {
-                Log::debug("PluginsArchiver::%s: Skipping archiving for plugin '%s'.", __FUNCTION__, $pluginName);
+                Log::debug("PluginsArchiver::%s: Skipping archiving for plugin '%s' (disabled).", __FUNCTION__, $pluginName);
+                continue;
+            }
+
+            if (!$forceArchivingWithoutVisits && !$visits && !$archiver->shouldRunEvenWhenNoVisits()) {
+                Log::debug("PluginsArchiver::%s: Skipping archiving for plugin '%s' (no visits).", __FUNCTION__, $pluginName);
                 continue;
             }
 
@@ -161,12 +166,28 @@ class PluginsArchiver
         return $this->archiveWriter->getIdArchive();
     }
 
+    /**
+     * Returns if any plugin archiver archives without visits
+     */
+    public static function doesAnyPluginArchiveWithoutVisits()
+    {
+        $archivers = static::getPluginArchivers();
+
+        foreach ($archivers as $pluginName => $archiverClass) {
+            if ($archiverClass::shouldRunEvenWhenNoVisits()) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     /**
      * Loads Archiver class from any plugin that defines one.
      *
      * @return \Piwik\Plugin\Archiver[]
      */
-    protected function getPluginArchivers()
+    protected static function getPluginArchivers()
     {
         if (empty(static::$archivers)) {
             $pluginNames = \Piwik\Plugin\Manager::getInstance()->getActivatedPlugins();
diff --git a/core/CronArchive.php b/core/CronArchive.php
index bac5aabcda926660cc80169959186e7b03816acb..cc8a1de71c85a459f103d7ab90930ccc81977b22 100644
--- a/core/CronArchive.php
+++ b/core/CronArchive.php
@@ -9,6 +9,7 @@
 namespace Piwik;
 
 use Exception;
+use Piwik\ArchiveProcessor\PluginsArchiver;
 use Piwik\ArchiveProcessor\Rules;
 use Piwik\Archiver\Request;
 use Piwik\Container\StaticContainer;
@@ -816,9 +817,11 @@ class CronArchive
         $this->requests++;
         $this->processed++;
 
+        $shouldArchiveWithoutVisits = PluginsArchiver::doesAnyPluginArchiveWithoutVisits();
+
         // If there is no visit today and we don't need to process this website, we can skip remaining archives
         if (
-            0 == $visitsToday
+            0 == $visitsToday && !$shouldArchiveWithoutVisits
             && !$shouldArchivePeriods
         ) {
             $this->logger->info("Skipped website id $idSite, no visit today, " . $timerWebsite->__toString());
@@ -827,7 +830,7 @@ class CronArchive
             return false;
         }
 
-        if (0 == $visitsLastDays
+        if (0 == $visitsLastDays && !$shouldArchiveWithoutVisits
             && !$shouldArchivePeriods
             && $this->shouldArchiveAllSites
         ) {
diff --git a/core/Plugin/Archiver.php b/core/Plugin/Archiver.php
index 90e325bc8e14a7f0a99ba5f15738104e6c44a79a..fd247e0af65c6736759e216a33360d34a7f4ef6c 100644
--- a/core/Plugin/Archiver.php
+++ b/core/Plugin/Archiver.php
@@ -141,4 +141,16 @@ abstract class Archiver
     {
         return $this->enabled;
     }
+
+    /**
+     * By overwriting this method and returning true, a plugin archiver can force the archiving to run even when there
+     * was no visit for the website/date/period/segment combination
+     * (by default, archivers are skipped when there is no visit).
+     *
+     * @return bool
+     */
+    public static function shouldRunEvenWhenNoVisits()
+    {
+        return false;
+    }
 }
diff --git a/tests/PHPUnit/Integration/ArchiveProcessor/PluginsArchiverTest.php b/tests/PHPUnit/Integration/ArchiveProcessor/PluginsArchiverTest.php
index eaadfefe4508f296f5772895c1245f4dea72e280..3c22fd934c5efa6dc01e8119ab63d0a9c75e82fb 100644
--- a/tests/PHPUnit/Integration/ArchiveProcessor/PluginsArchiverTest.php
+++ b/tests/PHPUnit/Integration/ArchiveProcessor/PluginsArchiverTest.php
@@ -37,7 +37,7 @@ class CustomArchiver extends Archiver
 
 class CustomPluginsArchiver extends PluginsArchiver
 {
-    protected function getPluginArchivers()
+    protected static function getPluginArchivers()
     {
         return array(
             'MyPluginName' => 'Piwik\Tests\Integration\Archive\CustomArchiver'
diff --git a/tests/PHPUnit/Integration/ArchiveWithNoVisitsTest.php b/tests/PHPUnit/Integration/ArchiveWithNoVisitsTest.php
index 2063efdb253fa26001b2918740c4205ccf9ef2a3..8f541e2d5d721cb5e1a599c947d2e46296c86f83 100644
--- a/tests/PHPUnit/Integration/ArchiveWithNoVisitsTest.php
+++ b/tests/PHPUnit/Integration/ArchiveWithNoVisitsTest.php
@@ -20,6 +20,8 @@ class ArchiveWithNoVisitsTest_MockArchiver extends Archiver
 {
     public static $methodsCalled = array();
 
+    public static $runWithoutVisits = false;
+
     public function aggregateDayReport()
     {
         self::$methodsCalled[] = 'aggregateDayReport';
@@ -29,6 +31,11 @@ class ArchiveWithNoVisitsTest_MockArchiver extends Archiver
     {
         self::$methodsCalled[] = 'aggregateMultipleReports';
     }
+
+    public static function shouldRunEvenWhenNoVisits()
+    {
+        return self::$runWithoutVisits;
+    }
 }
 
 class ArchiveWithNoVisitsTest extends IntegrationTestCase
@@ -78,6 +85,28 @@ class ArchiveWithNoVisitsTest extends IntegrationTestCase
         $this->assertEquals($expectedMethodCalls, ArchiveWithNoVisitsTest_MockArchiver::$methodsCalled);
     }
 
+    public function test_PluginArchiver_CanBeUsedToTriggerArchiving_EvenIfSiteHasNoVisits()
+    {
+        PluginsArchiver::$archivers['VisitsSummary'] = 'Piwik\Tests\Integration\ArchiveWithNoVisitsTest_MockArchiver';
+
+        ArchiveWithNoVisitsTest_MockArchiver::$runWithoutVisits = true;
+
+        // initiate archiving and make sure methods are called
+        VisitsSummaryAPI::getInstance()->get($idSite = 1, 'week', '2012-01-01');
+
+        $expectedMethodCalls = array(
+            'aggregateDayReport',
+            'aggregateDayReport',
+            'aggregateDayReport',
+            'aggregateDayReport',
+            'aggregateDayReport',
+            'aggregateDayReport',
+            'aggregateDayReport',
+            'aggregateMultipleReports',
+        );
+        $this->assertEquals($expectedMethodCalls, ArchiveWithNoVisitsTest_MockArchiver::$methodsCalled);
+    }
+
     /**
      * @return EventDispatcher
      */