Magento 2 generates PDF invoices out of the box — but the default layout is plain: logo, addresses, items, totals, and nothing else. There's no admin setting to add a footer with your company registration, VAT number, or bank details, no way to restyle the document. To change what's printed on the PDF, you have to override the invoice PDF model programmatically.
In this guide we'll build a small module that takes over PDF invoice generation and adds a custom footer to every page of the document — a pattern you can extend to any layout change you need.
Steps to Create a Custom Invoice PDF in Magento 2 Programmatically
We'll use Mageants_InvoicePdf as the module — replace the vendor and module names with your own throughout.
Step 1: Register the module at app/code/Mageants/InvoicePdf/registration.php<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Mageants_InvoicePdf',
__DIR__
);
|
Step 2: Create module.xml at app/code/Mageants/InvoicePdf/etc/module.xmlThe sequence entry makes sure our module loads after Magento_Sales, whose PDF model we're overriding: <?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Mageants_InvoicePdf" setup_version="1.0.0">
<sequence>
<module name="Magento_Sales"/>
</sequence>
</module>
</config>
|
Step 3: Create di.xml at app/code/Mageants/InvoicePdf/etc/di.xmlThis is the switch that makes the override work: a preference tells Magento's object manager to hand out our class everywhere the core invoice PDF model is requested: <?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\Sales\Model\Order\Pdf\Invoice" type="Mageants\InvoicePdf\Model\Order\Pdf\Invoice"/>
</config>
|
Step 4: Create Invoice.php at app/code/Mageants/InvoicePdf/Model/Order/Pdf/Invoice.phpOur class extends the core invoice PDF model. Three things happen here: getPdf() builds the document exactly like the core does (logo, addresses, order info, items, totals); our custom _drawFooter() draws a bordered footer box with your company details; and _afterGetPdf() stamps that footer onto every page of the document before it's returned: <?php
namespace Mageants\InvoicePdf\Model\Order\Pdf;
use Magento\Sales\Model\ResourceModel\Order\Invoice\Collection;
class Invoice extends \Magento\Sales\Model\Order\Pdf\Invoice
{
/**
* Return PDF document
*
* @param array|Collection $invoices
* @return \Zend_Pdf
*/
public function getPdf($invoices = [])
{
$this->_beforeGetPdf();
$this->_initRenderer('invoice');
$pdf = new \Zend_Pdf();
$this->_setPdf($pdf);
$style = new \Zend_Pdf_Style();
$this->_setFontBold($style, 10);
foreach ($invoices as $invoice) {
if ($invoice->getStoreId()) {
$this->_localeResolver->emulate($invoice->getStoreId());
$this->_storeManager->setCurrentStore($invoice->getStoreId());
}
$page = $this->newPage();
$order = $invoice->getOrder();
/* Add the store logo */
$this->insertLogo($page, $invoice->getStore());
/* Add the store address */
$this->insertAddress($page, $invoice->getStore());
/* Add the order info head */
$this->insertOrder(
$page,
$order,
$this->_scopeConfig->isSetFlag(
self::XML_PATH_SALES_PDF_INVOICE_PUT_ORDER_ID,
\Magento\Store\Model\ScopeInterface::SCOPE_STORE,
$order->getStoreId()
)
);
/* Add the document title and number */
$this->insertDocumentNumber($page, __('Invoice # ') . $invoice->getIncrementId());
/* Add the items table header */
$this->_drawHeader($page);
/* Draw each invoice item */
foreach ($invoice->getAllItems() as $item) {
if ($item->getOrderItem()->getParentItem()) {
continue;
}
$this->_drawItem($item, $page, $order);
$page = end($pdf->pages);
}
/* Add the totals block */
$this->insertTotals($page, $invoice);
if ($invoice->getStoreId()) {
$this->_localeResolver->revert();
}
}
$this->_afterGetPdf();
return $pdf;
}
/**
* Draw the custom footer — put whatever your invoices legally
* need here: company registration, VAT number, bank details.
*
* @param \Zend_Pdf_Page $page
* @return void
*/
protected function _drawFooter(\Zend_Pdf_Page $page)
{
$this->y = 50;
$page->setFillColor(new \Zend_Pdf_Color_RGB(1, 1, 1));
$page->setLineColor(new \Zend_Pdf_Color_GrayScale(0.5));
$page->setLineWidth(0.5);
$page->drawRectangle(70, $this->y, 510, $this->y - 30);
$page->setFillColor(new \Zend_Pdf_Color_RGB(0.1, 0.1, 0.1));
$page->setFont(\Zend_Pdf_Font::fontWithName(\Zend_Pdf_Font::FONT_HELVETICA), 7);
$this->y -= 10;
$page->drawText('Example Company B.V. - Registration No. 12345678', 180, $this->y, 'UTF-8');
$page->drawText('VAT: NL123456789B01 - IBAN: NL00 BANK 0123 4567 89 - support@example.com', 120, $this->y -= 15, 'UTF-8');
}
/**
* Stamp the footer on every page of the finished document
*
* @return void
*/
protected function _afterGetPdf()
{
foreach ($this->_getPdf()->pages as $page) {
$this->_drawFooter($page);
}
parent::_afterGetPdf();
}
}
|
Step 5: Enable the module and testRun these commands from the Magento root: php bin/magento module:enable Mageants_InvoicePdf php bin/magento setup:upgrade php bin/magento setup:di:compile php bin/magento cache:flush Then generate a PDF to see the result: in the admin, go to Sales > Invoices, open any invoice, and click Print — or select several invoices and use the PDF Invoices mass action. The downloaded document now carries your footer on every page. |
Customizing the PDF Further
The footer is just the demonstration — with the override in place, _drawFooter() and getPdf() are yours to edit: reposition blocks, change fonts and colors, add tax breakdowns or barcodes. Two things you don't need code for: the logo and store address printed at the top come from Stores > Configuration > Sales > Sales > Invoice and Packing Slip Design, so set those in the admin first.
Be aware of the trade-off, though: a preference replaces the core class outright, so every Magento upgrade that touches invoice PDF generation needs your override re-checked — and drawing layouts coordinate-by-coordinate in Zend_Pdf gets tedious fast for anything beyond small tweaks. If you'd rather design invoices like documents instead of plotting text at x/y positions, the PDF Invoice extension for Magento 2 lets you build fully branded templates for invoices, orders, shipments, and credit memos from the admin — custom fields, styling, and multi-language output, no override to maintain. The use guide shows the template builder in detail.
Conclusion
That's the complete pattern for customizing invoice PDFs in Magento 2: a di.xml preference to take over the core model, and an override class where getPdf() controls the document and a helper like _drawFooter() adds what the default leaves out. For a one-off footer or a small layout tweak, this module is all you need; for fully branded documents across all your sales paperwork, the extension route will save you the Zend_Pdf coordinate math. Either way, your invoices stop looking like everyone else's defaults — connect with MageAnts if you'd like help with either approach.