Skip to content

Hooks & filters

Easy Invoice exposes a large surface of apply_filters() and do_action() calls so you can extend behaviour without touching plugin files. This page lists the most useful hooks grouped by area, with file:line references for source-of-truth.

The list below is representative, not exhaustive — Easy Invoice fires hundreds of hooks across both plugins. For a full grep, run rg "apply_filters\|do_action" includes/ from each plugin root.

Bootstrap & lifecycle

HookTypeWhenFile:line
easy_invoice_loadedactionAfter the free plugin and constants are loaded.easy-invoice.php:106
easy_invoice_after_admin_scriptsactionAfter admin assets are enqueued.easy-invoice.php:152
php
add_action( 'easy_invoice_loaded', function () {
    // Safe place to register custom gateways or settings.
} );

Settings

HookTypeUse
easy_invoice_settings_fields_configfilterAdd / modify settings sections and fields.
easy_invoice_settings_for_displayfilterMutate settings before rendering.
easy_invoice_settings_tabsfilterRegister new top-level settings tab.
easy_invoice_settings_email_placeholdersfilterAdd merge tags to the email editor.
easy_invoice_settings_template_pathfilterOverride the settings template file.
easy_invoice_after_settings_pageactionRender extra HTML after the settings form.
php
add_filter( 'easy_invoice_settings_fields_config', function ( $config ) {
    $config['advanced']['fields']['my_custom_toggle'] = [
        'label'   => 'Enable my feature',
        'type'    => 'checkbox',
        'default' => '0',
    ];
    return $config;
} );

Invoice model

HookTypeUse
easy_invoice_model_to_arrayfilterTransform invoice when serialising.
easy_invoice_invoice_totalfilterOverride how totals are computed.
easy_invoice_invoice_query_argsfilterModify WP_Query args for the invoice list.
easy_invoice_invoice_createdactionNew invoice saved.
easy_invoice_invoice_updatedactionExisting invoice updated.
easy_invoice_invoice_deletedactionInvoice trashed.

Quote model

Same pattern with easy_invoice_quote_* prefix:

  • easy_invoice_quote_created / _updated / _deleted
  • easy_invoice_quote_accepted / _declined
php
add_action( 'easy_invoice_quote_accepted', function ( $quote_id ) {
    // Auto-create a kickoff invoice when a quote is accepted.
} );

Payments

HookTypeUse
easy_invoice_payment_completedactionFired when a payment settles the invoice. Args: $invoice_id, $invoice, $payment (payment_method, gateway_name, transaction_id, amount, date).
easy_invoice_payment_receivedactionFired when a payment is recorded that still leaves a balance owing (partial payment). Same arguments.
easy_invoice_before_process_paymentactionBefore gateway processes (good for validation).
easy_invoice_should_update_invoice_statusfilterDecide whether the parent invoice status should change.
easy_invoice_pro_recurring_generatedactionFires after a recurring invoice is generated (Pro).
easy_invoice_pro_receipt_generatedactionFires after a receipt is generated (Pro).
php
add_action( 'easy_invoice_payment_completed', function ( $invoice_id, $invoice, $payment ) {
    // Notify external CRM that we got paid: $payment['amount'] via $payment['gateway_name'].
}, 10, 3 );

Emails

HookTypeUse
easy_invoice_email_sentactionAfter successful wp_mail.
easy_invoice_email_failedactionWhen wp_mail returns false.
easy_invoice_email_attachmentsfilterAdd / remove email attachments.
easy_invoice_email_headersfilterChange the headers of an outgoing email. Args: $headers, $kind (invoice, quote, receipt, reminder, or '' ), $document.
easy_invoice_email_footer_htmlfilterThe footer block of every email ('' when no footer text is set). Args: $footer_html, $settings.
easy_invoice_email_htmlfilterReplace the whole email layout: return a full HTML document. Args: '', $message, $logo_html, $footer_html, $settings.
easy_invoice_pdf_footer_htmlfilterThe footer printed under a document on the page, the PDF and the email attachment. Args: $text, $document, $type.
php
add_filter( 'easy_invoice_email_attachments', function ( $attachments, $type, $invoice_id ) {
    if ( $type === 'invoice_available' ) {
        $attachments[] = WP_CONTENT_DIR . '/uploads/terms.pdf';
    }
    return $attachments;
}, 10, 3 );

Gateways

Custom gateways register against:

  • easy_invoice_payment_gateways — array of gateway instances.
  • easy_invoice_before_process_payment — pre-process hook.
  • easy_invoice_{gateway}_payment_complete — gateway-specific complete action.

Pro-specific:

  • easy_invoice_authorizenet_payment_complete (AuthorizeNetGateway.php:470+).
  • easy_invoice_stripe_payment_complete.
  • etc.
php
add_action( 'easy_invoice_stripe_payment_complete', function ( $payment_id, $charge_id ) {
    // Custom post-payment logic.
}, 10, 2 );

Frontend templates

Override a template from your theme (2.4.0+)

Copy any file from the plugin's templates/ folder to wp-content/themes/{your-theme}/easy-invoice/ keeping the same relative path, and edit the copy. The child theme is checked first, then the parent, then the plugin — the same convention as WooCommerce, and it survives plugin updates.

WhatCopy to
The public invoice / quote page (action bar, payment panel){theme}/easy-invoice/document/single.php
A design, e.g. Modern{theme}/easy-invoice/invoice-templates/modern.php or quote-templates/modern.php
The PDF layouts{theme}/easy-invoice/pdf/invoice.php, pdf/quote.php, pdf/statement.php
The payment panel{theme}/easy-invoice/payment-section.php

The page template receives $document, $document_type (invoice or quote), $invoice / $quote, $formatter, $text_settings and $template_file. Start from the plugin's copy rather than a blank file — it fires the hooks the Pro addons (PDF Toolkit, Partial Payments, Additional Tax) render into.

HookTypeUse
easy_invoice_locate_templatefilter( $path, $template, $args ) — final say on which file is used; return '' to declare it missing.
easy_invoice_template_directoryfilterFolder name inside the theme, default easy-invoice.
easy_invoice_document_isolate_assetsfilterDefault true: the theme's styles and scripts are kept off the document page. Return false to let them in.
easy_invoice_document_allowed_handlesfilterHandles to keep alongside the plugin's own when isolation is on.
easy_invoice_document_script_configfilterStrings and settings handed to the page's script.
easy_invoice_document_actionsaction( $document, $document_type ) — add a button to the action bar.
easy_invoice_document_footeractionBefore wp_footer() on the document page.
easy_invoice_headactionInside <head> of the document page, after wp_head(). Prefer wp_enqueue_scripts with \EasyInvoice\Services\DocumentPage::currentType() for new code.
easy_invoice_invoice_view_content_top / easy_invoice_quote_view_content_topactionAbove the design, inside the content frame.
easy_invoice_invoice_totals_after_tax / easy_invoice_quote_totals_after_taxactionExtra total lines.
single_templatefilter (WP core)Still honoured; the plugin's own resolution runs first.
php
// Let the theme's fonts onto the invoice page but nothing else.
add_filter( 'easy_invoice_document_allowed_handles', function ( $handles ) {
    $handles[] = 'my-theme-fonts';
    return $handles;
} );

Pro-only extensions

HookTypeUse
easy_invoice_pro_templatesfilterRegister extra template builder templates.
easy_invoice_pro_export_fieldsfilterAdd columns to CSV export.
easy_invoice_pro_is_client_invoicefilterDecide whether a request is "client-context" (portal).
easy_invoice_can_download_pdffilterPrivacy gate for PDF download.
easy_invoice_can_view_invoicefilterPrivacy gate for the public invoice view.
easy_invoice_display_totalfilterOverride what's rendered in the total area (used by Partial Payments).
php
add_filter( 'easy_invoice_can_download_pdf', function ( $can, $invoice_id, $user ) {
    if ( ! $user ) return false;
    return user_can( $user, 'manage_options' ) || $can;
}, 10, 3 );

Repository / data layer

HookTypeUse
easy_invoice_invoice_repository_argsfilterModify repo query args.
easy_invoice_client_repository_argsfilterSame for clients.
easy_invoice_payment_repository_argsfilterSame for payments.

Reports

HookTypeUse
easy_invoice_reports_datafilterMutate the data passed to Chart.js.
easy_invoice_reports_template_pathfilterUse your own report template.

Naming convention

  • Free plugin prefixes hooks with easy_invoice_*.
  • Pro plugin uses easy_invoice_pro_* for new hooks added by Pro modules; reuses free hooks for shared behaviour.

Tip: discover all hooks at runtime

For exhaustive coverage in a specific install, drop this in wp-content/mu-plugins/easy-invoice-hooks.php:

php
<?php
add_action( 'all', function ( $hook_name ) {
    if ( strpos( $hook_name, 'easy_invoice' ) === 0 ) {
        error_log( "[Easy Invoice hook] $hook_name" );
    }
} );

This logs every Easy Invoice hook that fires during a request.

Where to go next