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 factures aren't just boring paperwork – they're part of your brand experience. The default facture template gets the job done, but it looks... well, default. Creating a custom facture template vous permet de:

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

The good news? Magento 2 makes this personnalisation surprisingly straightforward once you know où look. Parcourons ensemble the process étape par étape.

Understanding Magento 2's Invoice Structure

Avant we start coding, it helps to understand how Magento handles factures:

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

All facture-related fichiers live in the vendor/magento/module-sales module, but we'll create our own version in our thème to override the defaults.

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

Premièrement, make sure you have a custom thème 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 facture template by copying and modifying the default one.

Create this répertoire structure in your thème:

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

Copy the default items.phtml fichier from:

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

Paste it into your new répertoire. C'est the fichier we'll modify to customize our facture appearance.

Step 3: Customize the Invoice HTML

Open your copied items.phtml fichier. Here's a simple exemple 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 fichier de layout. Create this fichier:

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

With this contenu:

<?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 fichier at:

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

Add your styles there. For exemple:

.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 factures, go to:

  1. Panneau d'administration → 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 champs like PO numbers or special instructions? Voici comment:

Premièrement, create a plugin to add your custom data to the facture e-mail. Create this fichier:

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

With this contenu:

<?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

Après making all these changes, it's crucial to test:

  1. Create a test commande
  2. Generate an facture for it
  3. Send the facture e-mail to yourself
  4. Check both HTML and plain text versions

To manually trigger an facture e-mail from the admin:

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

Advanced Customization: PDF Invoices

Si vous want your personnalisations to also appear on PDF factures, you'll need to override the PDF renderer. Create this fichier:

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

Extend the core class and override the méthodes you need. The most important one is getPdf() which generates the PDF contenu.

Problèmes courants and Dépannage

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

Problem: Emails not sending
Solution: Check your e-mail configuration under Stores → Configuration → Sales → Sales Emails

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

Réflexions finales

Customizing your Magento 2 facture templates is a great way to reinforce your brand and improve client experience. Tandis que the process might seem technical at first, breaking it down into these étapes makes it manageable.

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

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