Send tax receipts for donations, with Mechanic.

Mechanic is a development and ecommerce automation platform for Shopify. :)

Send tax receipts for donations

Use this task to email donation receipts to donors as PDF attachments, with an option to cc the shop email. It runs on new, paid orders, or optionally on order creation. The task will sum the donation amount from all line items that have any of the configured donation product tags or titles.

Runs Occurs whenever an order is paid and Occurs when a user sends an order to Mechanic. Configuration includes tax id, run on order creation instead of paid, identify donation products with any of these tags, identify donation products with any of these titles, send cc to shop email, email subject, email body, donation receipt filename, and donation reciept html template.

15-day free trial – unlimited tasks

Documentation

Use this task to email donation receipts to donors as PDF attachments, with an option to cc the shop email. It runs on new, paid orders, or optionally on order creation. The task will sum the donation amount from all line items that have any of the configured donation product tags or titles.

This task can also receive individual orders sent directly via admin action links.

Notes:

  • The task comes with a sample donation tag, email subject, email body, donation receipt filename, and donation receipt HTML template. The HTML template is used by the PDF file generator, so care must be taken to provide valid HTML if this field is customized.
  • The [TAX_ID] and [DONATION_AMOUNT] variables need to be present in the HTML template in order for those values to be included in the PDF donation receipt.
  • Orders with no donation products will be ignored by this task.

Developer details

Mechanic is designed to benefit everybody: merchants, customers, developers, agencies, Shopifolks, everybody.

That’s why we make it easy to configure automation without code, why we make it easy to tweak the underlying code once tasks are installed, and why we publish it all here for everyone to learn from.

(By the way, have you seen our documentation? Have you joined the Slack community?)

Open source
View on GitHub to contribute to this task
Subscriptions
{% if options.run_on_order_creation_instead_of_paid__boolean %}
  shopify/orders/create
{% else %}
  shopify/orders/paid
{% endif %}
mechanic/user/order
Tasks use subscriptions to sign up for specific kinds of events. Learn more
Options
tax id (required), run on order creation instead of paid (boolean), identify donation products with any of these tags (array), identify donation products with any of these titles (array), send cc to shop email (boolean), email subject (required), email body (multiline, required), donation receipt filename (required), donation reciept html template (code, multiline, required)
Code
{% assign tax_id = options.tax_id__required %}
{% comment %}{{ options.run_on_order_creation_instead_of_paid__boolean }}{% endcomment %}
{% assign donation_product_tags = options.identify_donation_products_with_any_of_these_tags__array %}
{% assign donation_product_titles = options.identify_donation_products_with_any_of_these_titles__array %}
{% assign send_cc_to_shop_email = options.send_cc_to_shop_email__boolean %}
{% assign email_subject = options.email_subject__required %}
{% assign email_body = options.email_body__multiline_required %}
{% assign donation_receipt_filename = options.donation_receipt_filename__required %}
{% assign donation_reciept_html_template = options.donation_reciept_html_template__code_multiline_required %}

{% if donation_product_tags == blank and donation_product_titles == blank %}
  {% error "Enter at least one product tag or title to filter on." %}
{% endif %}

{% if event.topic == "shopify/orders/paid"
  or event.topic == "shopify/orders/create"
  or event.topic == "mechanic/user/order"
%}
  {% if order.email == blank %}
    {% log "This order does not have an email associated with it." %}
    {% break %}
  {% endif %}

  {% comment %}
    -- get the order data to see if there are any donation products on this order, by product tag or title
  {% endcomment %}

  {% capture query %}
    query {
      order(id: {{ order.admin_graphql_api_id | json }}) {
        id
        presentmentCurrencyCode
        lineItems(first: 100) {
          nodes {
            product {
              tags
              title
            }
            originalTotalSet {
              presentmentMoney {
                amount
              }
            }
          }
        }
      }
    }
  {% endcapture %}

  {% assign result = query | shopify %}

  {% if event.preview %}
    {% capture result_json %}
      {
        "data": {
          "order": {
            "presentmentCurrencyCode": "USD",
            "lineItems": {
              "nodes": [
                {
                  "product": {
                    "tags": {{ donation_product_tags.first | json }},
                    "title": {{ donation_product_titles.first | json }}
                  },
                  "originalTotalSet": {
                    "presentmentMoney": {
                      "amount": "100.0"
                    }
                  }
                }
              ]
            }
          }
        }
      }
    {% endcapture %}

    {% assign result = result_json | parse_json %}
  {% endif %}

  {% comment %}
    -- for any donation products, add the non-discounted total for that line item to the runnning donation amount
  {% endcomment %}

  {% assign donation_amount = 0 %}

  {% for line_item in result.data.order.lineItems.nodes %}
    {% assign is_donation_product = nil %}

    {% for donation_product_tag in donation_product_tags %}
      {% if line_item.product.tags contains donation_product_tag %}
        {% assign is_donation_product = true %}
        {% break %}
      {% endif %}
    {% endfor %}

    {% for donation_product_title in donation_product_titles %}
      {% if line_item.product.title == donation_product_title %}
        {% assign is_donation_product = true %}
        {% break %}
      {% endif %}
    {% endfor %}

    {% if is_donation_product %}
      {% assign donation_amount = donation_amount | plus: line_item.originalTotalSet.presentmentMoney.amount %}
    {% endif %}
  {% endfor %}

  {% unless donation_amount > 0 %}
    {% log "This order has no donation products on it; skipping" %}
    {% break %}
  {% endunless %}

  {% assign donation_with_currency = donation_amount | currency: result.data.order.presentmentCurrencyCode %}

  {% comment %}
    -- replace variables in the HTML template for the configured tax ID and the calculated donation amount
  {% endcomment %}

  {% assign donation_html
    = donation_reciept_html_template
    | replace: "[TAX_ID]", tax_id
    | replace: "[DONATION_AMOUNT]", donation_with_currency
  %}

  {% comment %}
    -- generate tax receipt as a PDF and attach to email to donor; optionally cc the shop email address
  {% endcomment %}

  {% action "email" %}
    {
      "to": {{ order.email | json }},
      "subject": {{ email_subject | json }},
      "body": {{ email_body | newline_to_br | json }},
      {% if send_cc_to_shop_email %}"cc": {{ shop.customer_email | json }},{% endif %}
      "reply_to": {{ shop.customer_email | json }},
      "from_display_name": {{ shop.name | json }},
      "attachments": {
        {{ donation_receipt_filename | remove: "#" | json }}: {
          "pdf": {
            "html": {{ donation_html | json }},
            "__force_pdfcrowd": true
          }
        }
      }
    }
  {% endaction %}
{% endif %}
Task code is written in Mechanic Liquid, an extension of open-source Liquid enhanced for automation. Learn more
Defaults
Email subject
Receipt {{ order.name }} for donation to {{ shop.name }}
Email body
Thank you for your recent donation!

Attached you will find your official donation receipt.
Donation receipt filename
{{ shop.name | handleize }}-donation-receipt-{{ order.name  }}.pdf
Donation reciept HTML template
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <style>
    .container {
      width: 960px;
      margin: 0 auto;
      font-size: 16px;
    }
    .header {
      display: flex;
      flex-direction: row;
      border-top: 1px solid #000; 
      border-bottom: 1px dashed #000; 
      font-size: 18px;
    }
    .main {
      margin-top: 10px;
      display: flex;
      flex-direction: row;
      font-size: 16px;
    }
    .left {
      width: 50%;
    }
    .right {
      width: 50%;
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="header">
      <p class="left">
        {{ shop.name }}<br/>
        {{ shop.address1 }}<br/>{% if shop.address2 != blank -%}{{ shop.address2 }}<br/>{%- endif %}
        {{ shop.city }}, {{ shop.province }} {{ shop.zip }}<br/>
        {{ order.billing_address.country }}
      </p>
      <p class="right">
        OFFICIAL DONATION RECEIPT<br/>
        TAX ID #[TAX_ID]<br/>
      </p>
    </div>
    <div class="main">
      <p class="left">
        <strong>Donor:</strong><br/>
        {{ order.billing_address.first_name }} {{ billing_address.last_name }}<br/>
        {{ order.billing_address.address1 }}<br/>{% if order.billing_address.address2 != blank -%}{{ order.billing_address.address2 }}<br/>{%- endif %}
        {{ order.billing_address.city }}, {{ order.billing_address.province }} {{ order.billing_address.zip }}<br/>
        {{ order.billing_address.country }}
      </p>
      <p class="right">
        <strong>Donation Details:</strong><br/>
        Order Number: {{ order.name }}<br/>
        Donation Received: {{ order.created_at | date: "%F" }}<br/>
        Amount: [DONATION_AMOUNT]<br/>
        Date Issued: {{ "now" | date: "%F" }}<br/>
        Place Issued: {{ shop.province }}, {{ shop.country_name }}<br/>
        <br/>
        Donations are tax deductible to the extent permitted by law.<br/>
        <br/>
        Thank you
      </p>
    </div>
  </div>
</body>
</html>