
Attach a file to the WooCommerce Order Completed email if a specific product or variation is in the order.
This post was inspired by Ray’s comment on my Add info to WooCommerce order emails post. He wanted to attach a file to the Completed Order email if specific product variations were in the order (a later comment had a changed requirement but I had already explored attachments so I’m writing about that!).
There’s a filter for that
Like almost every part of WooCommerce (and WordPress) there’s a filter to extend it. There’s the ‘woocommerce_email_attachments‘ to allow you add a list of files to attach to WooCommerce emails. The filter function receives 3 additional parameters to help you decide whether to attach files.
The first additional parameter is the email ID, a string to identify which email is being sent. The code verifies that the email ID is ‘customer_completed_order.’
Examine the ordered items
Another of the additional parameters in an object – it could be a product object (in the case of ‘low stock’ and ‘no stock’ notifications), a user object (new customer account email) or an order object (for order status emails).
The Completed Order email code (handled by WC_Email_Customer_Completed_Order class in includes/emails/class-wc-email-customer-completed-order.php sets it to an order object. The code gets a list of the items and loops through them, gets the product and then the product ID.
Attach a file
For this demonstration I used a site that had the Storefront theme and the default products that it adds. I decided to add a file when the order contained the Belt product or the Medium, Blue variation of the Long Sleeve Tee product.
Get the product or variation ID
As the code needs a product or variation ID we need to find the appropriate ones. It’s quite easy.

The product ID shows when you hover over the product row in the Products page in the Dashboard.
For a variable product you need to go to its Edit Product page and open the Variations section.

Path to the attachment file
I browsed my site’s uploads directory and found the relative directory for the Belt and Long Sleeve Tee images. I used the wp_get_upload_dir() function to get information about the path to the uploads area and use the ‘basedir‘ member of that information for the top level directory (note that I do not use the url of the directory or the file!).
It works
WooCommerce takes care of actually attaching the files to the email. It just works!

Hi Damien,
Can this code be altered to attach a PDF to categories instead of single products ?I would like to set it up upon order completed , globally according to 3 categories that have 2 global product variations.
@Dhane – Yes, you could check the product’s categories instead of the ID. I suggest replacing the switch() block with code like:
if ( has_term( array( 'cat1', 'cat2', 'cat3' ), 'product_tag', $product ) ) { $attachments[] = '/path/to/attachment'; }
I have not tried that code out.
Hi,
Great code but what can i use to do this.
Product ID 23 with attachment ID 88
Product ID 25 with attachment ID 102
This is what i am trying to use ( but no attachment ).
add_filter( 'woocommerce_email_attachments', 'dcwd_conditionally_attach_files_to_order_email', 10, 4 ); function dcwd_conditionally_attach_files_to_order_email( $attachments, $email_id, $object, $email_obj, $email_order ) { // Only attach files to Completed Order email, otherwise return early. if ( 'new_order' != $email_id ) { return $attachments; }
$upload_dir = wp_get_upload_dir();
// Retrieve items in the order and examine each one. $items = $object->get_items(); foreach ( $items as $item_id => $item ) { $product = $item->get_product();
switch ( $product->get_id() ) { // NED (ID 863) case 863: $attachments[] = $upload_dir[ 'basedir' ] . '/2021/02/APG_NED_Alle_Kleuren.pdf'; break; // ENG (ID 896) case 896: $attachments[] = $upload_dir[ 'basedir' ] . '/2021/04/APG_ENG_Alle_Kleuren.pdf'; break; } } return $attachments; }
@John – The get_attached_file( $attachment_id ) returns the path to the attachment with ID of $attachment_id.
In the switch( $product->get_id() ) you could use:
case 23: $attachments[] = get_attached_file( 88 ); break; case 25: $attachments[] = get_attached_file( 102 ); break;