If we look at this module-catalog\view\frontend\templates\product\list.phtml around line 80 There is function $_product->isSaleable() which then again call to isSalable() function of Magento\Catalog\Model\Product.
There are two events in it catalog_product_is_salable_before and catalog_product_is_salable_after. Depending on your need you can modify it.
I used catalog_product_is_salable_after event to hide Add to Cart button
namespace Namespace\Module\Observer\Frontend; use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; class classname implements ObserverInterface { public $request; public function __construct( \Magento\Framework\App\Request\Http $request ) { $this->request = $request; } public function execute(Observer $observer) { if ($this->request->getFullActionName() == 'catalog_category_view') { $product = $observer->getEvent()->getProduct(); $saleble = $observer->getEvent()->getSalable(); if($product->getTypeId() == 'customProductType') { $saleble->setIsSalable(false); $salable = $product->getStatus() == \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED; if ($salable && $product->hasData('is_salable')) { $salable = $product->getData('is_salable'); } $product->setIsSaleable($salable); } } return $this; } } Though this will add In Stock or Out of Stock in place of Add to Cart.