Auto-tag customers that accept marketing, with Mechanic.

Mechanic is a development platform for Shopify. :)

Auto-tag customers that accept marketing

Use this task to auto-tag customers whose marketing preferences have been updated, adding a tag for those that do accept marketing and removing it from customers who do not. Optionally, choose whether to limit tags to customers who have single or confirmed opt-in levels. Run this task manually to scan all customers at once.

Runs when a customer is updated, when a user triggers the task, and when a bulk operation finishes. Configuration includes customer tag to add, only tag confirmed opt ins, and tag both single and confirmed opt ins.

15-day free trial – unlimited tasks

Documentation

Use this task to auto-tag customers whose marketing preferences have been updated, adding a tag for those that do accept marketing and removing it from customers who do not. Optionally, choose whether to limit tags to customers who have single or confirmed opt-in levels. Run this task manually to scan all customers at once.

Learn more from Shopify about confirmed opt-in (aka double opt-in), and how to configure this for your store.

Note: Running this task manually will sync that tag for ALL customers that accept marketing (and if checked, with required opt-in level), regardless of when their marketing preferences were last updated. If you have many customers, running this task manually could take a long time!

Developer details

Mechanic is designed to benefit everybody: merchants, customers, developers, agencies, Gurus, 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.

Open source
View on GitHub to contribute to this task
Events
when a customer is updated (shopify/customers/update)
when a user triggers the task (mechanic/user/trigger)
when a bulk operation finishes (mechanic/shopify/bulk_operation)
Options
customer tag to add (required), only tag confirmed opt ins (boolean), tag both single and confirmed opt ins (boolean)
Script
{% comment %}
  Options ordering:
  {{ options.customer_tag_to_add__required }}
  {{ options.only_tag_confirmed_opt_ins__boolean }}
  {{ options.tag_both_single_and_confirmed_opt_ins__boolean }}
{% endcomment %}

{% if options.only_tag_confirmed_opt_ins__boolean and options.tag_both_single_and_confirmed_opt_ins__boolean %}
  {% error "Choose either 'Only tag confirmed opt-ins' and 'Tag single and confirmed opt-ins', or neither, but not both" %}
{% endif %}

{% if event.topic contains "shopify/customers/" %}
  {% if event.preview %}
    {% assign customer = hash %}
    {% assign customer["admin_graphql_api_id"] = "gid://shopify/Customer/1234567890" %}
    {% assign customer["accepts_marketing"] = true %}
    {% assign customer["updated_at"] = "2021-01-01T12:34:56-07:00" %}
    {% assign customer["accepts_marketing_updated_at"] = "2021-01-01T12:34:56-07:00" %}
    {% assign customer["marketing_opt_in_level"] = "confirmed_opt_in" %}
    {% assign customer["tags"] = "" %}
  {% endif %}

  {% assign customer_tags = customer.tags | split: ", " %}

  {% if customer.updated_at == customer.accepts_marketing_updated_at %}
    {% assign qualifies_for_tag = false %}

    {% if options.only_tag_confirmed_opt_ins__boolean %}
      {% if customer.marketing_opt_in_level == "confirmed_opt_in" %}
        {% assign qualifies_for_tag = true %}
      {% endif %}
    {% elsif options.tag_both_single_and_confirmed_opt_ins__boolean %}
      {% if customer.marketing_opt_in_level == "confirmed_opt_in" or customer.marketing_opt_in_level == "single_opt_in" %}
        {% assign qualifies_for_tag = true %}
      {% endif %}
    {% elsif customer.accepts_marketing %}
      {% assign qualifies_for_tag = true %}
    {% endif %}

    {% if qualifies_for_tag %}
      {% unless customer_tags contains options.customer_tag_to_add__required %}
        {% action "shopify" %}
          mutation {
            tagsAdd(
              id: {{ customer.admin_graphql_api_id | json }}
              tags: {{ options.customer_tag_to_add__required | json }}
            ) {
              userErrors {
                field
                message
              }
            }
          }
        {% endaction %}
      {% endunless %}
    {% elsif customer_tags contains options.customer_tag_to_add__required %}
      {% action "shopify" %}
        mutation {
          tagsRemove(
            id: {{ customer.admin_graphql_api_id | json }}
            tags: {{ options.customer_tag_to_add__required | json }}
          ) {
            userErrors {
              field
              message
            }
          }
        }
      {% endaction %}
    {% endif %}

  {% else %}
    {% log message: "Customer update does not appear to be marketing preference related by timestamp; skipping", customer_updated_at: customer.updated_at, accepts_marketing_updated_at: customer.accepts_marketing_updated_at %}
  {% endif %}

{% elsif event.topic == "mechanic/user/trigger" %}
  {% capture bulk_operation_query %}
    query {
      customers {
        edges {
          node {
            id
            tags
            acceptsMarketing
            marketingOptInLevel
          }
        }
      }
    }
  {% endcapture %}

  {% action "shopify" %}
    mutation {
      bulkOperationRunQuery(
        query: {{ bulk_operation_query | json }}
      ) {
        bulkOperation {
          id
          status
        }
        userErrors {
          field
          message
        }
      }
    }
  {% endaction %}

{% elsif event.topic == "mechanic/shopify/bulk_operation" %}
  {% if event.preview %}
    {% capture bulkOperation_objects_jsonl %}
      {"id":"gid:\/\/shopify\/Customer\/1234567890","tags":[],"acceptsMarketing":true,"marketingOptInLevel":"SINGLE_OPT_IN"}
      {"id":"gid:\/\/shopify\/Customer\/2345678901","tags":[{{ options.customer_tag_to_add__required | json }}],"acceptsMarketing":false,"marketingOptInLevel":null}
      {"id":"gid:\/\/shopify\/Customer\/3456789012","tags":[{{ options.customer_tag_to_add__required | json }}],"acceptsMarketing":true,"marketingOptInLevel":"SINGLE_OPT_IN"}
      {"id":"gid:\/\/shopify\/Customer\/4567890123","tags":[],"acceptsMarketing":true,"marketingOptInLevel":"CONFIRMED_OPT_IN"}
    {% endcapture %}

    {% assign bulkOperation = hash %}
    {% assign bulkOperation["objects"] = bulkOperation_objects_jsonl | parse_jsonl %}
  {% endif %}

  {% for customer in bulkOperation.objects %}
    {% assign qualifies_for_tag = false %}

    {% if options.only_tag_confirmed_opt_ins__boolean %}
      {% if customer.marketingOptInLevel == "CONFIRMED_OPT_IN" %}
        {% assign qualifies_for_tag = true %}
      {% endif %}
    {% elsif options.tag_both_single_and_confirmed_opt_ins__boolean %}
      {% if customer.marketingOptInLevel == "CONFIRMED_OPT_IN" or customer.marketingOptInLevel == "SINGLE_OPT_IN" %}
        {% assign qualifies_for_tag = true %}
      {% endif %}
    {% elsif customer.acceptsMarketing %}
      {% assign qualifies_for_tag = true %}
    {% endif %}

    {% if qualifies_for_tag %}
      {% unless customer.tags contains options.customer_tag_to_add__required %}
        {% action "shopify" %}
          mutation {
            tagsAdd(
              id: {{ customer.id | json }}
              tags: {{ options.customer_tag_to_add__required | json }}
            ) {
              userErrors {
                field
                message
              }
            }
          }
        {% endaction %}
      {% endunless %}
    {% elsif customer.tags contains options.customer_tag_to_add__required %}
      {% action "shopify" %}
        mutation {
          tagsRemove(
            id: {{ customer.id | json }}
            tags: {{ options.customer_tag_to_add__required | json }}
          ) {
            userErrors {
              field
              message
            }
          }
        }
      {% endaction %}
    {% endif %}
  {% endfor %}
{% endif %}
Mechanic tasks are written in Liquid, which makes them easy to write and easy to modify. Learn more about our platform.