How to Create a Custom Invoice Template in Magento 2

Why Custom Invoice Templates Matter in Magento 2

If you're running a Magento 2 store, you know that facturas aren't just boring paperwork – they're part of your brand experience. The default factura template gets the job done, but it looks... well, default. Creating a custom factura template le permite:

  • Match your brand colors and logo
  • Add custom fields like PO numbers or special instructions
  • Improve readability for your customers
  • Include promotional messages or loyalty program details

The good news? Magento 2 makes this customization surprisingly straightforward once you know dónde look. Recorramos juntos the process paso a paso.

Understanding Magento 2's Invoice Structure

Antes de we start coding, it helps to understand how Magento handles facturas:

  1. Layout files define the structure (XML)
  2. Templates handle the HTML/PHP rendering
  3. CSS styles control the appearance

All factura-related files live in the vendor/magento/module-sales module, but we'll create our own version in our theme to override the defaults.

Step 1: Create Your Custom Theme (If You Haven't Already)

Primero, make sure you have a custom theme set up. If you're already using one, skip to Step 2.

In your Magento installation:

app/design/frontend/<Vendor>/<Theme>/
├── registration.php
├── theme.xml
└── web/
    ├── css/
    ├── images/
    └── js/

Your registration.php should look like:

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::THEME,
    'frontend/<Vendor>/<Theme>',
    __DIR__
);

And theme.xml:

<theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Config/etc/theme.xsd">
    <title>Your Theme Name</title>
    <parent>Magento/blank</parent>
</theme>

Step 2: Override the Invoice Template

Now we'll create our custom factura template by copying and modifying the default one.

Create this directory structure in your theme:

app/design/frontend/<Vendor>/<Theme>/Magento_Sales/templates/order/email/invoice/

Copy the default items.phtml file from:

vendor/magento/module-sales/view/frontend/templates/order/email/invoice/items.phtml

Paste it into your new directory. Esto es the file we'll modify to customize our factura appearance.

Step 3: Customize the Invoice HTML

Open your copied items.phtml file. Here's a simple example of how you might modify it:

<?php
/**
 * Custom invoice template
 */
?>
<table class="email-items" style="width:100%; font-family: Arial, sans-serif;">
    <thead>
        <tr>
            <th class="item-info" style="text-align:left; padding:10px; background:#f5f5f5;">
                <?= $block->escapeHtml(__('Product')) ?>
            </th>
            <th class="item-qty" style="text-align:left; padding:10px; background:#f5f5f5;">
                <?= $block->escapeHtml(__('Qty')) ?>
            </th>
            <th class="item-price" style="text-align:left; padding:10px; background:#f5f5f5;">
                <?= $block->escapeHtml(__('Price')) ?>
            </th>
        </tr>
    </thead>
    <tbody>
        <?php foreach ($_items as $_item): ?>
            <?php if (!$_item->getOrderItem()->getParentItem()) : ?>
                <tr>
                    <td class="item-info" style="padding:10px; border-bottom:1px solid #eee;">
                        <p class="product-name"><?= $block->escapeHtml($_item->getName()) ?></p>
                        <?php if ($_options = $block->getItemOptions($_item)): ?>
                            <dl class="item-options">
                                <?php foreach ($_options as $_option) : ?>
                                    <dt><?= $block->escapeHtml($_option['label']) ?></dt>
                                    <?php if (!$block->getPrintStatus()): ?>
                                        <?php $_formatedOptionValue = $block->getFormatedOptionValue($_option) ?>
                                        <dd>
                                            <?php if (isset($_formatedOptionValue['full_view'])): ?>
                                                <?= $_formatedOptionValue['full_view'] ?>
                                            <?php else: ?>
                                                <?= $_formatedOptionValue['value'] ?>
                                            <?php endif; ?>
                                        </dd>
                                    <?php endif; ?>
                                <?php endforeach; ?>
                            </dl>
                        <?php endif; ?>
                    </td>
                    <td class="item-qty" style="padding:10px; border-bottom:1px solid #eee;">
                        <?= (float)$_item->getQty() ?>
                    </td>
                    <td class="item-price" style="padding:10px; border-bottom:1px solid #eee;">
                        <?= /* @noEscape */ $block->getItemPrice($_item) ?>
                    </td>
                </tr>
            <?php endif; ?>
        <?php endforeach; ?>
    </tbody>
    <tfoot>
        <?= $block->getChildHtml('invoice_totals') ?>
    </tfoot>
</table>

Step 4: Customize the Invoice Layout

To make sure our template is used, we need to override the layout file. Create this file:

app/design/frontend/<Vendor>/<Theme>/Magento_Sales/layout/sales_email_order_invoice_items.xml

With this content:

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="items">
            <action method="setTemplate">
                <argument name="template" xsi:type="string">Magento_Sales::order/email/invoice/items.phtml</argument>
            </action>
        </referenceBlock>
    </body>
</page>

Step 5: Add Custom CSS

For more advanced styling, create a custom CSS file at:

app/design/frontend/<Vendor>/<Theme>/web/css/source/_email-invoice.less

Add your styles there. For example:

.email-invoice {
    .logo {
        text-align: center;
        margin-bottom: 20px;
        
        img {
            max-width: 200px;
        }
    }
    
    .invoice-details {
        background: #f9f9f9;
        padding: 15px;
        margin-bottom: 20px;
        
        .invoice-title {
            color: @primary__color;
            font-size: 18px;
            margin-bottom: 10px;
        }
    }
    
    .order-details {
        margin-bottom: 30px;
    }
}

Step 6: Add Your Company Logo

To add your logo to facturas, go to:

  1. Panel de administración → Stores → Configuration
  2. Sales → Sales Emails
  3. Upload your logo under "Logo for HTML Email"
  4. Set the width to an appropriate size (usually 200px)

Step 7: Adding Custom Fields

Need to add custom fields like PO numbers or special instructions? Así es como:

Primero, create a plugin to add your custom data to the factura email. Create this file:

app/code/<Vendor>/<Module>/Plugin/Sales/Order/Invoice.php

With this content:

<?php
namespace <Vendor>\<Module>\Plugin\Sales\Order;

class Invoice
{
    public function beforeGetEmailCustomVariables(
        \Magento\Sales\Model\Order\Invoice $subject,
        $result
    ) {
        $order = $subject->getOrder();
        
        // Add your custom data here
        $result['custom_field'] = $order->getData('your_custom_field');
        
        return [$result];
    }
}

Then reference this data in your template:

<?php if (isset($custom_field) && $custom_field): ?>
    <div class="custom-field">
        <strong><?= __('Custom Field') ?>:</strong>
        <span><?= $custom_field ?></span>
    </div>
<?php endif; ?>

Step 8: Testing Your Custom Invoice

Después de making all these changes, it's crucial to test:

  1. Create a test order
  2. Generate an factura for it
  3. Send the factura email to yourself
  4. Check both HTML and plain text versions

To manually trigger an factura email from the admin:

  1. Go to Sales → Invoices
  2. Find your test factura
  3. Click "Send Email"

Advanced Customization: PDF Invoices

Si usted want your customizations to also appear on PDF facturas, you'll need to override the PDF renderer. Create this file:

app/code/<Vendor>/<Module>/Model/Order/Pdf/Invoice.php

Extend the core class and override the methods you need. The most important one is getPdf() which generates the PDF content.

Problemas comunes and Solución de problemas

Problem: Changes aren't appearing
Solution: Clear cache and static content: php bin/magento cache:flush and php bin/magento setup:static-content:deploy

Problem: Emails not sending
Solution: Check your email configuration under Stores → Configuration → Sales → Sales Emails

Problem: Layout breaks in email clients
Solution: Stick to simple table-based layouts and inline CSS for maximum compatibility

Reflexiones finales

Customizing your Magento 2 factura templates is a great way to reinforce your brand and improve customer experience. Mientras the process might seem technical at first, breaking it down into these steps makes it manageable.

Remember that facturas are legal documents, so always include all required information. Beyond that, let your brand personality shine through!

Need more advanced customizations? Check out our Magento 2 extensions that can help streamline your invoicing process even further.