I was able to get product collection by using layerResolver like this: Vendor/Module/Controller/Index/Index.php ``` public function __construct( \Magento\Framework\App\Action\Context $context, \Magento\Framework\View\Result\PageFactory $pageFactory, \Magento\Catalog\Model\Layer\Resolver $layerResolver ) { $this->layerResolver = $layerResolver; $this->pageFactory = $pageFactory; $this->context = $context; parent::__construct($context); } public function execute() { $date = new \Zend_Date(); $result = $this->pageFactory->create(); $this->layerResolver->create('search'); $collection = $this->layerResolver->get()->getProductCollection(); $collection->('special_price', ['gt'=>0],'left'); $collection ->addAttributeToFilter( 'special_from_date', [ 'or' => [ 0 => [ 'date' => true, 'to' => $date->get('YYYY-MM-dd').' 23:59:59'], 1 => [ 'is' => new \Zend_Db_Expr('null') ], ] ], 'left' )->addAttributeToFilter( 'special_to_date', [ 'or' => [ 0 => [ 'date' => true, 'from' => $date->get('YYYY-MM-dd').' 00:00:00'], 1 => [ 'is' => new \Zend_Db_Expr('null') ], ] ], 'left' ); $list = $result->getLayout()->getBlock('custom.products.list'); $list->setProductCollection($collection); return $result; } ``` To avoid problems with aggregations and buckets I use this: Vendor/Module/etc/di.xml ``` <?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <!-- To prepare the filterlist for our custom collection which would be passed to the left navigation we need below virtual types for our custom page navigation --> <virtualType name="customFilterList" type="Vendor\Module\Model\Layer\FilterList"> <arguments> <argument name="filterableAttributes" xsi:type="object">Vendor\Module\Model\Layer\FilterableAttributeList</argument> <argument name="filters" xsi:type="array"> <item name="attribute" xsi:type="string">Vendor\Module\Model\Layer\Filter\Attribute</item> <item name="category" xsi:type="string">Vendor\Module\Model\Layer\Filter\Category</item> </argument> </arguments> </virtualType> <!-- once the filter list virtual type is ready we can pass the same to our navigation , I have prepared the virtual type of the core navigation for my custom module and have passed the custom filter list to it --> <virtualType name="Vendor\Module\Block\Navigation\Custnavigation" type="Magento\LayeredNavigation\Block\Navigation"> <arguments> <argument name="filterList" xsi:type="object">customFilterList</argument> </arguments> </virtualType> </config> ``` Vendor/Module/Model/Layer/FilterableAttributeList.php ``` namespace Vendor\Module\Model\Layer; class FilterableAttributeList extends \Magento\Catalog\Model\Layer\Category\FilterableAttributeList { } ``` Vendor/Module/Model/Layer/FilterList.php ``` namespace Vendor\Module\Model\Layer; class FilterList extends \Magento\Catalog\Model\Layer\FilterList { } ``` Vendor/Module/Model/Layer/Filter/Attribute.php ``` namespace Vendor\Module\Model\Layer\Filter; class Attribute extends \Magento\Catalog\Model\Layer\Filter\Attribute { } ``` Vendor/Module/Model/Layer/Filter/Category.php ``` namespace Vendor\Module\Model\Layer\Filter; class Category extends \Magento\CatalogSearch\Model\Layer\Filter\Category { } ``` Vendor/Module/view/frontend/layout/custompage_index_index.xml ``` <?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left"> <body> <attribute name="class" value="page-with-filter"/> <referenceContainer name="sidebar.main"> <block class="Vendor\Module\Block\Navigation\Custnavigation" name="catalog.leftnav" before="-" template="Magento_LayeredNavigation::layer/view.phtml"> <block class="Magento\LayeredNavigation\Block\Navigation\State" name="catalog.navigation.state" as="state" /> <block class="Magento\LayeredNavigation\Block\Navigation\FilterRenderer" name="catalog.navigation.renderer" as="renderer" template="Magento_LayeredNavigation::layer/filter.phtml"/> </block> </referenceContainer> <referenceContainer name="content"> <block class="Vendor\Module\Block\Product\CustomList" name="custom.products.list" as="product_list" template="Magento_Catalog::product/list.phtml"> <container name="category.product.list.additional" as="additional" /> <block class="Magento\Framework\View\Element\RendererList" name="category.product.type.details.renderers" as="details.renderers"> <block class="Magento\Framework\View\Element\Template" as="default"/> </block> <block class="Magento\Catalog\Block\Product\ProductList\Toolbar" name="product_list_toolbar" template="Magento_Catalog::product/list/toolbar.phtml"> <block class="Magento\Theme\Block\Html\Pager" name="product_list_toolbar_pager"/> </block> <action method="setToolbarBlockName"> <argument name="name" xsi:type="string">product_list_toolbar</argument> </action> </block> </referenceContainer> </body> </page> ``` Vendor/Module/Block/Product/CustomList.php ``` namespace Vendor\Module\Block\Product; use Magento\Catalog\Block\Product\ListProduct; use Magento\Catalog\Model\ResourceModel\Collection\AbstractCollection; class CustomList extends ListProduct { public function getLoadedProductCollection() { return $this->_productCollection; } public function setProductCollection(AbstractCollection $collection) { $this->_productCollection = $collection; } } ``` This will give you filtered collection on custom page via available special price today. Most of this code was found here on Stack Exchange in questions with layered-navigation tag.