diff --git a/core/Archive.php b/core/Archive.php
index c7eb6e310619bcf1083a4834fe3834bb44a1358c..049975641066c17bd21d9449239e86a7813038c0 100644
--- a/core/Archive.php
+++ b/core/Archive.php
@@ -498,7 +498,11 @@ class Archive
 
         $dataTable = self::getDataTableFromArchive($recordName, $idSite, $period, $date, $segment, $expanded, $idSubtable, $depth);
 
-        $dataTable->filter('ReplaceColumnNames');
+        $dataTable->queueFilter('ReplaceColumnNames');
+
+        if ($expanded) {
+            $dataTable->queueFilterSubtables('ReplaceColumnNames');
+        }
 
         if ($flat) {
             $dataTable->disableRecursiveFilters();
diff --git a/core/DataTable.php b/core/DataTable.php
index 0b0d9845f0e835d6a4c99e8354d512ffac95030d..935ee34bfa4320e1cbb8a3417020a3159a1aa10b 100644
--- a/core/DataTable.php
+++ b/core/DataTable.php
@@ -488,6 +488,25 @@ class DataTable implements DataTableInterface, \IteratorAggregate, \ArrayAccess
         }
     }
 
+    /**
+     * Applies a filter to all subtables but not to this datatable.
+     *
+     * @param string|Closure $className Class name, eg. `"Sort"` or "Piwik\DataTable\Filters\Sort"`. If no
+     *                                  namespace is supplied, `Piwik\DataTable\BaseFilter` is assumed. This parameter
+     *                                  can also be a closure that takes a DataTable as its first parameter.
+     * @param array $parameters Array of extra parameters to pass to the filter.
+     */
+    public function queueFilterSubtables($className, $parameters = array())
+    {
+        foreach ($this->getRows() as $row) {
+            $subtable = $row->getSubtable();
+            if ($subtable) {
+                $subtable->queueFilter($className, $parameters);
+                $subtable->queueFilterSubtables($className, $parameters);
+            }
+        }
+    }
+
     /**
      * Adds a filter and a list of parameters to the list of queued filters. These filters will be
      * executed when {@link applyQueuedFilters()} is called.
diff --git a/core/DataTable/Filter/Sort.php b/core/DataTable/Filter/Sort.php
index 632da35dc8394bf5c17833b2b7949e39519dedbd..3da11b411947d8f5e8cc45b064aba1bec4169471 100644
--- a/core/DataTable/Filter/Sort.php
+++ b/core/DataTable/Filter/Sort.php
@@ -143,9 +143,9 @@ Sort extends BaseFilter
             );
     }
 
-    protected function getColumnValue(Row $table )
+    protected function getColumnValue(Row $row)
     {
-        $value = $table->getColumn($this->columnToSort);
+        $value = $row->getColumn($this->columnToSort);
 
         if ($value === false
             || is_array($value)
diff --git a/core/DataTable/Map.php b/core/DataTable/Map.php
index 8787b064045cacf393504318d833a4498444211d..ccf201c5be90bec1b6292c00a7c904ad36510326 100644
--- a/core/DataTable/Map.php
+++ b/core/DataTable/Map.php
@@ -122,6 +122,19 @@ class Map implements DataTableInterface
         }
     }
 
+    /**
+     * Apply a queued filter to all subtables contained by this instance.
+     *
+     * @param string|Closure $className Name of filter class or a Closure.
+     * @param array $parameters Parameters to pass to the filter.
+     */
+    public function queueFilterSubtables($className, $parameters = array())
+    {
+        foreach ($this->getDataTables() as $table) {
+            $table->queueFilterSubtables($className, $parameters);
+        }
+    }
+
     /**
      * Returns the array of DataTables contained by this class.
      *
@@ -174,6 +187,20 @@ class Map implements DataTableInterface
         $this->array[$label] = $table;
     }
 
+    public function getRowFromIdSubDataTable($idSubtable)
+    {
+        $dataTables = $this->getDataTables();
+
+        // find first datatable containing data
+        foreach ($dataTables as $subTable) {
+            $subTableRow = $subTable->getRowFromIdSubDataTable($idSubtable);
+
+            if (!empty($subTableRow)) {
+                return $subTableRow;
+            }
+        }
+    }
+
     /**
      * Returns a string output of this DataTable\Map (applying the default renderer to every {@link DataTable}
      * of this DataTable\Map).
diff --git a/plugins/Actions/API.php b/plugins/Actions/API.php
index 7204ddfa50e980be2ff735745e1ca9c3330685eb..891400e1227bffd8e6dd8ed47c3e32242ef1927a 100644
--- a/plugins/Actions/API.php
+++ b/plugins/Actions/API.php
@@ -138,7 +138,7 @@ class API extends \Piwik\Plugin\API
     {
         // Keep only pages which are following site search
         $dataTable->filter('ColumnCallbackDeleteRow', array(
-            'nb_hits_following_search',
+            PiwikMetrics::INDEX_PAGE_IS_FOLLOWING_SITE_SEARCH_NB_HITS,
             function ($value) {
                 return $value <= 0;
             }
@@ -423,7 +423,7 @@ class API extends \Piwik\Plugin\API
 
             // end of tree search reached
             if (count($searchTree) == 0) {
-                $result = new DataTable();
+                $result = $table->getEmptyClone();
                 $result->addRow($row);
                 $result->setAllTableMetadata($table->getAllTableMetadata());
                 return $result;
@@ -471,7 +471,7 @@ class API extends \Piwik\Plugin\API
     private function filterNonEntryActions($dataTable)
     {
         $dataTable->filter('ColumnCallbackDeleteRow',
-            array('entry_nb_visits',
+            array(PiwikMetrics::INDEX_PAGE_ENTRY_NB_VISITS,
                   function ($visits) {
                       return !strlen($visits);
                   }
@@ -487,7 +487,7 @@ class API extends \Piwik\Plugin\API
     private function filterNonExitActions($dataTable)
     {
         $dataTable->filter('ColumnCallbackDeleteRow',
-            array('exit_nb_visits',
+            array(PiwikMetrics::INDEX_PAGE_EXIT_NB_VISITS,
                   function ($visits) {
                       return !strlen($visits);
                   })
diff --git a/plugins/Actions/Reports/Base.php b/plugins/Actions/Reports/Base.php
index 6d7146ae7359d28034df107d6556710f0458807d..45c9c0af9ccd2171ce326e72a6f6e85e3bb340e8 100644
--- a/plugins/Actions/Reports/Base.php
+++ b/plugins/Actions/Reports/Base.php
@@ -9,6 +9,7 @@
 namespace Piwik\Plugins\Actions\Reports;
 
 use Piwik\Common;
+use Piwik\Metrics;
 use Piwik\Metrics\Formatter;
 use Piwik\Piwik;
 use Piwik\Plugin\ViewDataTable;
@@ -91,7 +92,11 @@ abstract class Base extends \Piwik\Plugin\Report
     protected function addExcludeLowPopDisplayProperties(ViewDataTable $view)
     {
         if (Common::getRequestVar('enable_filter_excludelowpop', '0', 'string') != '0') {
-            $view->requestConfig->filter_excludelowpop = 'nb_hits';
+            if (Common::getRequestVar('flat', 0, 'int') === 1) {
+                $view->requestConfig->filter_excludelowpop = 'nb_hits';
+            } else {
+                $view->requestConfig->filter_excludelowpop = Metrics::INDEX_PAGE_NB_HITS;
+            }
             $view->requestConfig->filter_excludelowpop_value = function () {
                 // computing minimum value to exclude (2 percent of the total number of actions)
                 $visitsInfo = \Piwik\Plugins\VisitsSummary\Controller::getVisitsSummary()->getFirstRow();
diff --git a/plugins/CoreVisualizations/Visualizations/HtmlTable/RequestConfig.php b/plugins/CoreVisualizations/Visualizations/HtmlTable/RequestConfig.php
index c507d1857e971251339e24ab9ad8cafa9c42f2fa..2f674a587239917676fc33eff0710fa2c8700845 100644
--- a/plugins/CoreVisualizations/Visualizations/HtmlTable/RequestConfig.php
+++ b/plugins/CoreVisualizations/Visualizations/HtmlTable/RequestConfig.php
@@ -11,6 +11,7 @@ namespace Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable;
 
 use Piwik\Common;
 use Piwik\Config as PiwikConfig;
+use Piwik\Metrics;
 use Piwik\ViewDataTable\RequestConfig as VisualizationRequestConfig;
 
 /**
@@ -33,7 +34,12 @@ class RequestConfig extends VisualizationRequestConfig
         $this->filter_limit = PiwikConfig::getInstance()->General['datatable_default_limit'];
 
         if (Common::getRequestVar('enable_filter_excludelowpop', false) == '1') {
-            $this->filter_excludelowpop       = 'nb_visits';
+            if (Common::getRequestVar('flat', 0, 'int') === 1) {
+                $this->filter_excludelowpop = 'nb_visits';
+            } else {
+                $this->filter_excludelowpop = Metrics::INDEX_NB_VISITS;
+            }
+
             $this->filter_excludelowpop_value = false;
         }
 
diff --git a/plugins/CustomVariables/API.php b/plugins/CustomVariables/API.php
index 727ef7d42c42b195ea0ce9f67ebfda1c351ec529..1a6fc8c794d17249a9e9af25e0824edee4f8a785 100644
--- a/plugins/CustomVariables/API.php
+++ b/plugins/CustomVariables/API.php
@@ -12,7 +12,6 @@ use Piwik\Archive;
 use Piwik\DataTable;
 use Piwik\Date;
 use Piwik\Metrics;
-use Piwik\Piwik;
 use Piwik\Plugins\Actions\Actions\ActionSiteSearch;
 
 /**
@@ -32,12 +31,17 @@ class API extends \Piwik\Plugin\API
      *
      * @return DataTable|DataTable\Map
      */
-    protected function getDataTable($idSite, $period, $date, $segment, $expanded, $idSubtable)
+    protected function getDataTable($idSite, $period, $date, $segment, $expanded, $flat, $idSubtable)
     {
-        $dataTable = Archive::getDataTableFromArchive(Archiver::CUSTOM_VARIABLE_RECORD_NAME, $idSite, $period, $date, $segment, $expanded, $idSubtable);
+        $dataTable = Archive::createDataTableFromArchive(Archiver::CUSTOM_VARIABLE_RECORD_NAME, $idSite, $period, $date, $segment, $expanded, $flat, $idSubtable);
         $dataTable->filter('Sort', array(Metrics::INDEX_NB_ACTIONS, 'desc', $naturalSort = false, $expanded));
-        $dataTable->queueFilter('ReplaceColumnNames');
         $dataTable->queueFilter('ColumnDelete', 'nb_uniq_visitors');
+
+        if ($flat) {
+            $dataTable->filterSubtables('Sort', array(Metrics::INDEX_NB_ACTIONS, 'desc', $naturalSort = false, $expanded));
+            $dataTable->queueFilterSubtables('ColumnDelete', 'nb_uniq_visitors');
+        }
+
         return $dataTable;
     }
 
@@ -48,12 +52,13 @@ class API extends \Piwik\Plugin\API
      * @param string|bool $segment
      * @param bool $expanded
      * @param bool $_leavePiwikCoreVariables
+     * @param bool $flat
      *
      * @return DataTable|DataTable\Map
      */
-    public function getCustomVariables($idSite, $period, $date, $segment = false, $expanded = false, $_leavePiwikCoreVariables = false)
+    public function getCustomVariables($idSite, $period, $date, $segment = false, $expanded = false, $_leavePiwikCoreVariables = false, $flat = false)
     {
-        $dataTable = $this->getDataTable($idSite, $period, $date, $segment, $expanded, $idSubtable = null);
+        $dataTable = $this->getDataTable($idSite, $period, $date, $segment, $expanded, $flat, $idSubtable = null);
 
         if ($dataTable instanceof DataTable
             && !$_leavePiwikCoreVariables
@@ -66,6 +71,11 @@ class API extends \Piwik\Plugin\API
                 }
             }
         }
+
+        if ($flat) {
+            $dataTable->filterSubtables('Piwik\Plugins\CustomVariables\DataTable\Filter\CustomVariablesValuesFromNameId');
+        }
+
         return $dataTable;
     }
 
@@ -90,7 +100,7 @@ class API extends \Piwik\Plugin\API
      */
     public function getCustomVariablesValuesFromNameId($idSite, $period, $date, $idSubtable, $segment = false, $_leavePriceViewedColumn = false)
     {
-        $dataTable = $this->getDataTable($idSite, $period, $date, $segment, $expanded = false, $idSubtable);
+        $dataTable = $this->getDataTable($idSite, $period, $date, $segment, $expanded = false, $flat = false, $idSubtable);
 
         if (!$_leavePriceViewedColumn) {
             $dataTable->deleteColumn('price_viewed');
@@ -98,11 +108,8 @@ class API extends \Piwik\Plugin\API
             // Hack Ecommerce product price tracking to display correctly
             $dataTable->renameColumn('price_viewed', 'price');
         }
-        $dataTable->queueFilter('ColumnCallbackReplace', array('label', function ($label) {
-            return $label == \Piwik\Plugins\CustomVariables\Archiver::LABEL_CUSTOM_VALUE_NOT_DEFINED
-                ? Piwik::translate('General_NotDefined', Piwik::translate('CustomVariables_ColumnCustomVariableValue'))
-                : $label;
-        }));
+        $dataTable->filter('Piwik\Plugins\CustomVariables\DataTable\Filter\CustomVariablesValuesFromNameId');
+
         return $dataTable;
     }
 }
diff --git a/plugins/CustomVariables/DataTable/Filter/CustomVariablesValuesFromNameId.php b/plugins/CustomVariables/DataTable/Filter/CustomVariablesValuesFromNameId.php
new file mode 100644
index 0000000000000000000000000000000000000000..4bab2f290e6814c366d350a824db2ca56b1d25e0
--- /dev/null
+++ b/plugins/CustomVariables/DataTable/Filter/CustomVariablesValuesFromNameId.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\CustomVariables\DataTable\Filter;
+
+use Piwik\DataTable\BaseFilter;
+use Piwik\DataTable\Row;
+use Piwik\DataTable;
+use Piwik\Piwik;
+
+class CustomVariablesValuesFromNameId extends BaseFilter
+{
+
+    /**
+     * Constructor.
+     *
+     * @param DataTable $table The table to eventually filter.
+     */
+    public function __construct($table)
+    {
+        parent::__construct($table);
+    }
+
+    /**
+     * @param DataTable $table
+     */
+    public function filter($table)
+    {
+        $notDefinedLabel = Piwik::translate('General_NotDefined', Piwik::translate('CustomVariables_ColumnCustomVariableValue'));
+
+        $table->queueFilter('ColumnCallbackReplace', array('label', function ($label) use ($notDefinedLabel) {
+            return $label == \Piwik\Plugins\CustomVariables\Archiver::LABEL_CUSTOM_VALUE_NOT_DEFINED
+                ? $notDefinedLabel
+                : $label;
+        }));
+    }
+}
\ No newline at end of file
diff --git a/plugins/Referrers/API.php b/plugins/Referrers/API.php
index aa1a3e0419b5dad039fa67552f4e1d3f5430c0b0..bba6ca37af0aaefd28e3e1096af6726333a1b33e 100644
--- a/plugins/Referrers/API.php
+++ b/plugins/Referrers/API.php
@@ -13,6 +13,7 @@ use Piwik\API\ResponseBuilder;
 use Piwik\Archive;
 use Piwik\Common;
 use Piwik\DataTable\Row;
+use Piwik\DataTable\Manager as DataTableManager;
 use Piwik\DataTable;
 use Piwik\Date;
 use Piwik\Metrics;
@@ -136,19 +137,19 @@ class API extends \Piwik\Plugin\API
         return $dataTable;
     }
 
-    public function getKeywords($idSite, $period, $date, $segment = false, $expanded = false)
+    public function getKeywords($idSite, $period, $date, $segment = false, $expanded = false, $flat = false)
     {
-        $dataTable = $this->getDataTable(Archiver::KEYWORDS_RECORD_NAME, $idSite, $period, $date, $segment, $expanded);
-        $dataTable->filter('AddSegmentValue');
-        $dataTable->queueFilter('PrependSegment', array('referrerType==search;'));
+        $dataTable = Archive::createDataTableFromArchive(Archiver::KEYWORDS_RECORD_NAME, $idSite, $period, $date, $segment, $expanded, $flat);
 
-        $dataTable = $this->handleKeywordNotDefined($dataTable);
-        return $dataTable;
-    }
+        if ($flat) {
+            $dataTable->filterSubtables('Piwik\Plugins\Referrers\DataTable\Filter\SearchEnginesFromKeywordId', array($dataTable));
+        } else {
+            $dataTable->filter('AddSegmentValue');
+            $dataTable->queueFilter('PrependSegment', array('referrerType==search;'));
+        }
+
+        $dataTable->queueFilter('Piwik\Plugins\Referrers\DataTable\Filter\KeywordNotDefined');
 
-    protected function handleKeywordNotDefined($dataTable)
-    {
-        $dataTable->queueFilter('ColumnCallbackReplace', array('label', __NAMESPACE__ . '\API::getCleanKeyword'));
         return $dataTable;
     }
 
@@ -224,27 +225,28 @@ class API extends \Piwik\Plugin\API
     public function getSearchEnginesFromKeywordId($idSite, $period, $date, $idSubtable, $segment = false)
     {
         $dataTable = $this->getDataTable(Archiver::KEYWORDS_RECORD_NAME, $idSite, $period, $date, $segment, $expanded = false, $idSubtable);
-        $dataTable->queueFilter('ColumnCallbackAddMetadata', array('label', 'url', __NAMESPACE__ . '\getSearchEngineUrlFromName'));
-        $dataTable->queueFilter('MetadataCallbackAddMetadata', array('url', 'logo', __NAMESPACE__ . '\getSearchEngineLogoFromUrl'));
 
-        // get the keyword and create the URL to the search result page
         $keywords = $this->getKeywords($idSite, $period, $date, $segment);
-        $subTable = $keywords->getRowFromIdSubDataTable($idSubtable);
-        if ($subTable) {
-            $keyword = $subTable->getColumn('label');
-            $dataTable->queueFilter('MetadataCallbackReplace', array('url', __NAMESPACE__ . '\getSearchEngineUrlFromUrlAndKeyword', array($keyword)));
-        }
+        $dataTable->filter('Piwik\Plugins\Referrers\DataTable\Filter\SearchEnginesFromKeywordId', array($keywords, $idSubtable));
+
         return $dataTable;
     }
 
-    public function getSearchEngines($idSite, $period, $date, $segment = false, $expanded = false)
+    public function getSearchEngines($idSite, $period, $date, $segment = false, $expanded = false, $flat = false)
     {
-        $dataTable = $this->getDataTable(Archiver::SEARCH_ENGINES_RECORD_NAME, $idSite, $period, $date, $segment, $expanded);
+        $dataTable = Archive::createDataTableFromArchive(Archiver::SEARCH_ENGINES_RECORD_NAME, $idSite, $period, $date, $segment, $expanded, $flat);
+
+        if ($flat) {
+            $dataTable->filter('ColumnCallbackAddMetadata', array('label', 'url', __NAMESPACE__ . '\getSearchEngineUrlFromName'));
+            $dataTable->filter('MetadataCallbackAddMetadata', array('url', 'logo', __NAMESPACE__ . '\getSearchEngineLogoFromUrl'));
+            $dataTable->filterSubtables('Piwik\Plugins\Referrers\DataTable\Filter\KeywordsFromSearchEngineId', array($dataTable));
+        } else {
+            $dataTable->filter('AddSegmentByLabel', array('referrerName'));
+            $dataTable->queueFilter('PrependSegment', array('referrerType==search;'));
+            $dataTable->queueFilter('ColumnCallbackAddMetadata', array('label', 'url', __NAMESPACE__ . '\getSearchEngineUrlFromName'));
+            $dataTable->queueFilter('MetadataCallbackAddMetadata', array('url', 'logo', __NAMESPACE__ . '\getSearchEngineLogoFromUrl'));
+        }
 
-        $dataTable->filter('AddSegmentByLabel', array('referrerName'));
-        $dataTable->queueFilter('PrependSegment', array('referrerType==search;'));
-        $dataTable->queueFilter('ColumnCallbackAddMetadata', array('label', 'url', __NAMESPACE__ . '\getSearchEngineUrlFromName'));
-        $dataTable->queueFilter('MetadataCallbackAddMetadata', array('url', 'logo', __NAMESPACE__ . '\getSearchEngineLogoFromUrl'));
         return $dataTable;
     }
 
@@ -256,26 +258,8 @@ class API extends \Piwik\Plugin\API
         $searchEngines = $this->getSearchEngines($idSite, $period, $date, $segment);
         $searchEngines->applyQueuedFilters();
 
-        if ($searchEngines instanceof DataTable\Map) {
-            $dataTables = $searchEngines->getDataTables();
-
-            // find first datatable containing data
-            foreach ($dataTables as $subTable) {
-
-                $subTableRow = $subTable->getRowFromIdSubDataTable($idSubtable);
-                if (!empty($subTableRow)) {
-                    break;
-                }
-            }
-        } else {
-            $subTableRow = $searchEngines->getRowFromIdSubDataTable($idSubtable);
-        }
+        $dataTable->filter('Piwik\Plugins\Referrers\DataTable\Filter\KeywordsFromSearchEngineId', array($searchEngines, $idSubtable));
 
-        if (!empty($subTableRow)) {
-            $searchEngineUrl = $subTableRow->getMetadata('url');
-            $dataTable->queueFilter('ColumnCallbackAddMetadata', array('label', 'url', __NAMESPACE__ . '\getSearchEngineUrlFromKeywordAndUrl', array($searchEngineUrl)));
-        }
-        $dataTable = $this->handleKeywordNotDefined($dataTable);
         return $dataTable;
     }
 
@@ -325,11 +309,13 @@ class API extends \Piwik\Plugin\API
      * @param string $date
      * @param string|bool $segment
      * @param bool $expanded
+     * @param bool $flat
      * @return DataTable
      */
-    public function getSocials($idSite, $period, $date, $segment = false, $expanded = false)
+    public function getSocials($idSite, $period, $date, $segment = false, $expanded = false, $flat = false)
     {
-        $dataTable = $this->getDataTable(Archiver::WEBSITES_RECORD_NAME, $idSite, $period, $date, $segment, $expanded);
+        $dataTable = Archive::createDataTableFromArchive(Archiver::WEBSITES_RECORD_NAME, $idSite, $period, $date, $segment, $expanded, false);
+
         $dataTable->filter('ColumnCallbackDeleteRow', array('label', function ($url) { return !isSocialUrl($url); }));
         $dataTable->filter('ColumnCallbackAddMetadata', array('label', 'url', __NAMESPACE__ . '\getSocialMainUrl'));
         $dataTable->filter('GroupBy', array('label', __NAMESPACE__ . '\getSocialNetworkFromDomain'));
@@ -337,6 +323,36 @@ class API extends \Piwik\Plugin\API
         $this->setSocialIdSubtables($dataTable);
         $this->removeSubtableMetadata($dataTable);
 
+        if ($flat) {
+            $urlsTable = Archive::createDataTableFromArchive(Archiver::WEBSITES_RECORD_NAME, $idSite, $period, $date, $segment, $expanded, $flat);
+            $urlsTable->filter('ColumnCallbackDeleteRow', array('label', function ($url) { return !isSocialUrl($url); }));
+            $urlsTable = $urlsTable->mergeSubtables();
+
+            foreach ($dataTable->getRows() as $row) {
+                $row->removeSubtable();
+
+                $social   = $row->getColumn('label');
+                $newTable = $urlsTable->getEmptyClone();
+
+                $rows = $urlsTable->getRows();
+                foreach ($rows as $id => $urlsTableRow) {
+                    $url = $urlsTableRow->getColumn('label');
+                    if (isSocialUrl($url, $social)) {
+                        $newTable->addRow($urlsTableRow);
+                        $urlsTable->deleteRow($id);
+                    }
+                }
+
+                if ($newTable->getRowsCount()) {
+                    $newTable->filter('Piwik\Plugins\Referrers\DataTable\Filter\UrlsForSocial', array($expanded));
+                    $row->setSubtable($newTable);
+                }
+            }
+
+            Common::destroy($urlsTable);
+            $urlsTable = null;
+        }
+
         $dataTable->queueFilter('MetadataCallbackAddMetadata', array('url', 'logo', __NAMESPACE__ . '\getSocialsLogoFromUrl'));
 
         return $dataTable;
@@ -386,13 +402,7 @@ class API extends \Piwik\Plugin\API
         // merge the datatable's subtables which contain the individual URLs
         $dataTable = $dataTable->mergeSubtables();
 
-        // make url labels clickable
-        $dataTable->filter('ColumnCallbackAddMetadata', array('label', 'url'));
-
-        // prettify the DataTable
-        $dataTable->filter('ColumnCallbackReplace', array('label', __NAMESPACE__ . '\removeUrlProtocol'));
-        $dataTable->filter('Sort', array(Metrics::INDEX_NB_VISITS, 'desc', $naturalSort = false, $expanded));
-        $dataTable->queueFilter('ReplaceColumnNames');
+        $dataTable->filter('Piwik\Plugins\Referrers\DataTable\Filter\UrlsForSocial', array($expanded));
 
         return $dataTable;
     }
diff --git a/plugins/Referrers/DataTable/Filter/KeywordNotDefined.php b/plugins/Referrers/DataTable/Filter/KeywordNotDefined.php
new file mode 100644
index 0000000000000000000000000000000000000000..dbee6f865bd224d17a0a0955aa86a567bc9771b0
--- /dev/null
+++ b/plugins/Referrers/DataTable/Filter/KeywordNotDefined.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Referrers\DataTable\Filter;
+
+use Piwik\DataTable\Row;
+use Piwik\DataTable;
+
+class KeywordNotDefined extends DataTable\Filter\ColumnCallbackReplace
+{
+    /**
+     * Constructor.
+     *
+     * @param DataTable $table The table to eventually filter.
+     */
+    public function __construct($table)
+    {
+        parent::__construct($table, 'label', 'Piwik\Plugins\Referrers\API::getCleanKeyword');
+    }
+}
\ No newline at end of file
diff --git a/plugins/Referrers/DataTable/Filter/KeywordsFromSearchEngineId.php b/plugins/Referrers/DataTable/Filter/KeywordsFromSearchEngineId.php
new file mode 100644
index 0000000000000000000000000000000000000000..1688713a860b0d4f5e58c31f06e0a2b66f441168
--- /dev/null
+++ b/plugins/Referrers/DataTable/Filter/KeywordsFromSearchEngineId.php
@@ -0,0 +1,61 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Referrers\DataTable\Filter;
+
+use Piwik\DataTable\BaseFilter;
+use Piwik\DataTable\Row;
+use Piwik\DataTable;
+
+class KeywordsFromSearchEngineId extends BaseFilter
+{
+    /**
+     * @var DataTable
+     */
+    private $firstLevelSearchEnginesTable;
+
+    /**
+     * @var int
+     */
+    private $idSubtable;
+
+    /**
+     * Constructor.
+     *
+     * @param DataTable $table The table to eventually filter.
+     */
+    public function __construct($table, $firstLevelSearchEnginesTable, $idSubtable = null)
+    {
+        parent::__construct($table);
+
+        $this->firstLevelSearchEnginesTable = $firstLevelSearchEnginesTable;
+        $this->idSubtable = $idSubtable;
+    }
+
+    /**
+     * @param DataTable $table
+     */
+    public function filter($table)
+    {
+        $idSubtable  = $this->idSubtable ? : $table->getId();
+        $subTableRow = $this->firstLevelSearchEnginesTable->getRowFromIdSubDataTable($idSubtable);
+
+        if (!empty($subTableRow)) {
+            $searchEngineUrl = $subTableRow->getMetadata('url');
+            $table->queueFilter('ColumnCallbackAddMetadata', array('label', 'url', 'Piwik\Plugins\Referrers\getSearchEngineUrlFromKeywordAndUrl', array($searchEngineUrl)));
+            $table->queueFilter(function (DataTable $table) {
+                $row = $table->getRowFromId(DataTable::ID_SUMMARY_ROW);
+                if ($row) {
+                    $row->deleteMetadata('url');
+                }
+            });
+        }
+
+        $table->queueFilter('Piwik\Plugins\Referrers\DataTable\Filter\KeywordNotDefined');
+    }
+}
\ No newline at end of file
diff --git a/plugins/Referrers/DataTable/Filter/SearchEnginesFromKeywordId.php b/plugins/Referrers/DataTable/Filter/SearchEnginesFromKeywordId.php
new file mode 100644
index 0000000000000000000000000000000000000000..feab8636af46582c0d4f506bc92c4c9d21f576e2
--- /dev/null
+++ b/plugins/Referrers/DataTable/Filter/SearchEnginesFromKeywordId.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Referrers\DataTable\Filter;
+
+use Piwik\DataTable\BaseFilter;
+use Piwik\DataTable\Row;
+use Piwik\DataTable;
+
+class SearchEnginesFromKeywordId extends BaseFilter
+{
+    /**
+     * @var DataTable
+     */
+    private $firstLevelKeywordTable;
+
+    /**
+     * @var int
+     */
+    private $idSubtable;
+
+    /**
+     * Constructor.
+     *
+     * @param DataTable $table The table to eventually filter.
+     */
+    public function __construct($table, $firstLevelKeywordTable, $idSubtable = null)
+    {
+        parent::__construct($table);
+
+        $this->firstLevelKeywordTable = $firstLevelKeywordTable;
+        $this->idSubtable = $idSubtable;
+    }
+
+    /**
+     * @param DataTable $table
+     */
+    public function filter($table)
+    {
+        $idSubtable  = $this->idSubtable ? : $table->getId();
+
+        $table->queueFilter('ColumnCallbackAddMetadata', array('label', 'url', 'Piwik\Plugins\Referrers\getSearchEngineUrlFromName'));
+        $table->queueFilter('MetadataCallbackAddMetadata', array('url', 'logo', 'Piwik\Plugins\Referrers\getSearchEngineLogoFromUrl'));
+
+        // get the keyword and create the URL to the search result page
+        $rootRow = $this->firstLevelKeywordTable->getRowFromIdSubDataTable($idSubtable);
+        if ($rootRow) {
+            $keyword = $rootRow->getColumn('label');
+            $table->queueFilter('MetadataCallbackReplace', array('url', 'Piwik\Plugins\Referrers\getSearchEngineUrlFromUrlAndKeyword', array($keyword)));
+            $table->queueFilter(function (DataTable $table) {
+                $row = $table->getRowFromId(DataTable::ID_SUMMARY_ROW);
+                if ($row) {
+                    $row->deleteMetadata('url');
+                }
+            });
+        }
+    }
+}
\ No newline at end of file
diff --git a/plugins/Referrers/DataTable/Filter/UrlsForSocial.php b/plugins/Referrers/DataTable/Filter/UrlsForSocial.php
new file mode 100644
index 0000000000000000000000000000000000000000..ad86093060e59e9161d1e26178f48e41cfade5f3
--- /dev/null
+++ b/plugins/Referrers/DataTable/Filter/UrlsForSocial.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Referrers\DataTable\Filter;
+
+use Piwik\DataTable\BaseFilter;
+use Piwik\DataTable\Row;
+use Piwik\DataTable;
+use Piwik\Metrics;
+
+class UrlsForSocial extends BaseFilter
+{
+    /**
+     * @var bool
+     */
+    private $sortRecursive;
+
+    /**
+     * Constructor.
+     *
+     * @param DataTable $table The table to eventually filter.
+     * @param bool $sortRecursive Whether to sort recursive or not
+     */
+    public function __construct($table, $sortRecursive)
+    {
+        parent::__construct($table);
+
+        $this->sortRecursive = $sortRecursive;
+    }
+
+    /**
+     * @param DataTable $table
+     */
+    public function filter($table)
+    {
+        // make url labels clickable
+        $table->filter('ColumnCallbackAddMetadata', array('label', 'url'));
+
+        // prettify the DataTable
+        $table->filter('ColumnCallbackReplace', array('label', 'Piwik\Plugins\Referrers\removeUrlProtocol'));
+        $table->filter('Sort', array(Metrics::INDEX_NB_VISITS, 'desc', $naturalSort = false, $this->sortRecursive));
+        $table->queueFilter('ReplaceColumnNames');
+    }
+}
\ No newline at end of file
diff --git a/tests/PHPUnit/System/expected/test_reportLimiting_flattened__Referrers.getKeywords_day.xml b/tests/PHPUnit/System/expected/test_reportLimiting_flattened__Referrers.getKeywords_day.xml
index d093798ebf4432220b56f0c8226b3bffbe97f189..30316b9941bca03c12fbcca29c491319462be454 100644
--- a/tests/PHPUnit/System/expected/test_reportLimiting_flattened__Referrers.getKeywords_day.xml
+++ b/tests/PHPUnit/System/expected/test_reportLimiting_flattened__Referrers.getKeywords_day.xml
@@ -10,6 +10,8 @@
 		<sum_visit_length>0</sum_visit_length>
 		<bounce_count>1</bounce_count>
 		<nb_visits_converted>0</nb_visits_converted>
+		<url>http://ask.com/web?q=this+search+term</url>
+		<logo>plugins/Referrers/images/searchEngines/ask.com.png</logo>
 	</row>
 	<row>
 		<label>this search term - Others</label>
@@ -21,6 +23,7 @@
 		<sum_visit_length>0</sum_visit_length>
 		<bounce_count>2</bounce_count>
 		<nb_visits_converted>0</nb_visits_converted>
+		<logo>plugins/Referrers/images/searchEngines/xx.png</logo>
 	</row>
 	<row>
 		<label>search term 2 - Alexa</label>
@@ -32,6 +35,8 @@
 		<sum_visit_length>0</sum_visit_length>
 		<bounce_count>1</bounce_count>
 		<nb_visits_converted>0</nb_visits_converted>
+		<url>http://alexa.com/search?q=search+term+2</url>
+		<logo>plugins/Referrers/images/searchEngines/alexa.com.png</logo>
 	</row>
 	<row>
 		<label>search term 2 - Babylon</label>
@@ -43,6 +48,8 @@
 		<sum_visit_length>0</sum_visit_length>
 		<bounce_count>1</bounce_count>
 		<nb_visits_converted>0</nb_visits_converted>
+		<url>http://search.babylon.com/?q=search+term+2</url>
+		<logo>plugins/Referrers/images/searchEngines/search.babylon.com.png</logo>
 	</row>
 	<row>
 		<label>Others</label>
diff --git a/tests/PHPUnit/System/expected/test_reportLimiting_flattened__Referrers.getSearchEngines_day.xml b/tests/PHPUnit/System/expected/test_reportLimiting_flattened__Referrers.getSearchEngines_day.xml
index cb1d70e35beda3f9486ff17dc09d45fc5678b134..915b5ddb39216e98d5e986f5f70ac12a22a4cc96 100644
--- a/tests/PHPUnit/System/expected/test_reportLimiting_flattened__Referrers.getSearchEngines_day.xml
+++ b/tests/PHPUnit/System/expected/test_reportLimiting_flattened__Referrers.getSearchEngines_day.xml
@@ -10,6 +10,7 @@
 		<sum_visit_length>0</sum_visit_length>
 		<bounce_count>1</bounce_count>
 		<nb_visits_converted>0</nb_visits_converted>
+		<url>http://google.com/search?q=search+term+3</url>
 		<logo>plugins/Referrers/images/searchEngines/google.com.png</logo>
 	</row>
 	<row>
@@ -34,6 +35,7 @@
 		<sum_visit_length>0</sum_visit_length>
 		<bounce_count>1</bounce_count>
 		<nb_visits_converted>0</nb_visits_converted>
+		<url>http://search.yahoo.com/search?p=search+term+4</url>
 		<logo>plugins/Referrers/images/searchEngines/search.yahoo.com.png</logo>
 	</row>
 	<row>