Skip to content

Commit

Permalink
third batch of customer filter task fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
tekhaus committed Oct 31, 2024
1 parent 074a25e commit 0dbea45
Show file tree
Hide file tree
Showing 12 changed files with 638 additions and 427 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Tags: Auto-Tag, Customers, Location, Orders

When an order is created, this task adds the location of the purchase to the customer's tags. Useful for stores with multiple Shopify-powered locations.
When an order is created, this task adds the location name of the purchase to the customer's tags. Useful for stores with multiple Shopify-powered POS locations.

* View in the task library: [tasks.mechanic.dev/auto-tag-customers-with-the-location-of-their-purchase](https://tasks.mechanic.dev/auto-tag-customers-with-the-location-of-their-purchase)
* Task JSON, for direct import: [task.json](../../tasks/auto-tag-customers-with-the-location-of-their-purchase.json)
Expand All @@ -23,18 +23,17 @@ When an order is created, this task adds the location of the purchase to the cus
```liquid
shopify/orders/create
mechanic/user/trigger
mechanic/shopify/bulk_operation
```

[Learn about event subscriptions in Mechanic](https://learn.mechanic.dev/core/tasks/subscriptions)

## Documentation

When an order is created, this task adds the location of the purchase to the customer's tags. Useful for stores with multiple Shopify-powered locations.
When an order is created, this task adds the location name of the purchase to the customer's tags. Useful for stores with multiple Shopify-powered POS locations.

This task will run for each new order that's created, applying the order location as a customer tag. Optionally, define a tag to be used for orders that have no physical location.

Run this task manually to have Mechanic scan your entire customer base, and each customer's order history.
This task will run for each new order that's created, applying the POS location name as a customer tag. Optionally, define a tag to be used for online orders.

Run this task manually to have Mechanic scan each customer with an order history.

## Installing this task

Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,59 @@
{% assign tag_for_online_orders = options.tag_for_online_orders %}

{% if event.topic contains "shopify/orders" %}
{% capture query %}
query {
order(id: {{ order.admin_graphql_api_id | json }}) {
id
name
customer {
id
tags
}
retailLocation {
name
}
}
}
{% endcapture %}

{% assign result = query | shopify %}

{% if event.preview %}
{% capture order_json %}
{% capture result_json %}
{
"location": {
"name": "Storefront"
},
"customer": {
"admin_graphql_api_id": "gid://shopify/Customer/1234567890",
"tags": ""
"data": {
"order": {
"id": "gid://shopify/Order/1234567890",
"customer": {
"id": "gid://shopify/Customer/1234567890"
},
"retailLocation": {
"name": "Storefront"
}
}
}
}
{% endcapture %}

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

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

{% assign location = order.location.name | default: options.tag_for_online_orders %}
{% assign order = result.data.order %}
{% assign customer = order.customer %}
{% assign location_name = order.retailLocation.name | default: tag_for_online_orders %}

{% unless location == blank or customer_tags contains location %}
{% unless customer == blank or location_name == blank or customer.tags contains location_name %}
{% action "shopify" %}
mutation {
tagsAdd(
id: {{ order.customer.admin_graphql_api_id | json }}
tags: [{{ location | json }}]
id: {{ customer.id | json }}
tags: {{ location_name | json }}
) {
node {
... on Customer {
id
displayName
tags
}
}
Expand All @@ -39,88 +65,151 @@
}
{% endaction %}
{% endunless %}

{% elsif event.topic == "mechanic/user/trigger" %}
{% capture bulk_operation_query %}
query {
customers(query: "orders_count:>0") {
edges {
node {
__typename
id
tags
orders {
edges {
node {
__typename
id
physicalLocation {
name
}
}
}
{% comment %}
-- get IDs of all customers who have placed an order
{% endcomment %}

{% assign cursor = nil %}
{% assign customer_ids = array %}

{% for n in (1..100) %}
{% capture query %}
query {
customerSegmentMembers(
first: 1000
after: {{ cursor | json }}
query: "number_of_orders > 0"
) {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
id
}
}
}
}
}
{% 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 objects_jsonl %}
{"__typename":"Customer","id":"gid:\/\/shopify\/Customer\/1234567890","tags":[]}
{"__typename":"Order","id":"gid:\/\/shopify\/Order\/1234567890","physicalLocation":{"name":"Storefront"},"__parentId":"gid:\/\/shopify\/Customer\/1234567890"}
{% endcapture %}

{% assign bulkOperation = hash %}
{% assign bulkOperation["objects"] = objects_jsonl | parse_jsonl %}
{% assign result = query | shopify %}

{% assign customer_segment_members = result.data.customerSegmentMembers.edges | map: "node" %}

{% comment %}
-- remove the "SegmentMember" portion from IDs for easier use in querying each customer for additional data not available in the segment resource
{% endcomment %}

{% for customer_segment_member in customer_segment_members %}
{% assign customer_ids[customer_ids.size] = customer_segment_member.id | remove: "SegmentMember" %}
{% endfor %}

{% if result.data.customerSegmentMembers.pageInfo.hasNextPage %}
{% assign cursor = result.data.customerSegmentMembers.pageInfo.endCursor %}
{% else %}
{% break %}
{% endif %}
{% endfor %}

{% unless event.preview %}
{% log count_of_customers_who_have_placed_an_order: customer_ids.size %}
{% endunless %}

{% if event.preview %}
{% assign customer_ids[0] = "gid://shopify/Customer/1234567890" %}
{% endif %}

{% assign customers = bulkOperation.objects | where: "__typename", "Customer" %}
{% assign orders = bulkOperation.objects | where: "__typename", "Order" %}
{% for customer_id in customer_ids %}
{% comment %}
-- get all relevant order data for this customer
{% endcomment %}

{% for customer in customers %}
{% assign customer_orders = orders | where: "__parentId", customer.id %}
{% assign cursor = nil %}
{% assign tags_to_add = array %}

{% for order in customer_orders %}
{% assign location = order.physicalLocation.name | default: options.tag_for_online_orders %}
{% for n in (1..10) %}
{% capture query %}
query {
customer(id: {{ customer_id | json }}) {
id
tags
orders(
first: 250
after: {{ cursor | json }}
) {
pageInfo {
hasNextPage
endCursor
}
nodes {
id
name
retailLocation {
name
}
}
}
}
}
{% endcapture %}

{% assign result = query | shopify %}

{% if event.preview %}
{% capture result_json %}
{
"data": {
"customer": {
"id": "gid://shopify/Customer/1234567890",
"orders": {
"nodes": [
{
"id": "gid://shopify/Order/1234567890",
"retailLocation": {
"name": "Storefront"
}
}
]
}
}
}
}
{% endcapture %}

{% if location == blank or customer.tags contains location %}
{% continue %}
{% assign result = result_json | parse_json %}
{% endif %}

{% assign tags_to_add[tags_to_add.size] = location %}
{% assign customer = result.data.customer %}

{% comment %}
-- process orders to see which location names should be set as tags
{% endcomment %}

{% for order in customer.orders.nodes %}
{% assign location_name = order.retailLocation.name | default: tag_for_online_orders %}

{% unless location_name == blank or customer.tags contains location_name or tags_to_add contains location_name %}
{% assign tags_to_add = tags_to_add | push: location_name %}
{% endunless %}
{% endfor %}

{% if result.data.customer.orders.pageInfo.hasNextPage %}
{% assign cursor = result.data.customer.orders.pageInfo.endCursor %}
{% else %}
{% break %}
{% endif %}
{% endfor %}

{% if tags_to_add != empty %}
{% if tags_to_add != blank %}
{% action "shopify" %}
mutation {
tagsAdd(
id: {{ customer.id | json }}
tags: {{ tags_to_add | uniq | json }}
tags: {{ tags_to_add | sort_natural | json }}
) {
node {
... on Customer {
tags
}
}
userErrors {
field
message
Expand Down
32 changes: 15 additions & 17 deletions docs/copy-order-tags-to-customers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Tags: Auto-Tag, Customers

Run this task to scan all of your customers and their order histories in bulk, copying order and/or product tags to the relevant customer. Optionally, configure a specific set of tags to look for, when scanning. Optionally, choose to remove those tags if a qualifying source can't be found - useful for adding customer tags that expire after ordering!
Run this task to scan all of your customers and their order histories, copying order and/or product tags to the relevant customer. Optionally, configure a specific set of tags to look for, when scanning. Optionally, choose to remove those tags if a qualifying source can't be found.

* View in the task library: [tasks.mechanic.dev/copy-order-tags-to-customers](https://tasks.mechanic.dev/copy-order-tags-to-customers)
* Task JSON, for direct import: [task.json](../../tasks/copy-order-tags-to-customers.json)
Expand Down Expand Up @@ -31,28 +31,26 @@ mechanic/user/trigger
{% if options.run_daily__boolean %}
mechanic/scheduler/daily
{% endif %}
mechanic/shopify/bulk_operation
```

[Learn about event subscriptions in Mechanic](https://learn.mechanic.dev/core/tasks/subscriptions)

## Documentation

Run this task to scan all of your customers and their order histories in bulk, copying order and/or product tags to the relevant customer. Optionally, configure a specific set of tags to look for, when scanning. Optionally, choose to remove those tags if a qualifying source can't be found - useful for adding customer tags that expire after ordering!

Run this task to scan all of your customers and their order histories in bulk, copying order and/or product tags to the relevant customer. Optionally, configure a specific set of tags to look for, when scanning. Optionally, choose to remove those tags if a qualifying source can't be found.

Both the customer and order query options support Liquid. This means that you can dynamically query for orders, based on things like the current time.

For example, use these options to achieve customer tags that auto-expire a year after the newest qualifying order:

* "Only include orders matching this query": `created_at:>={{ "now" | date: "%s" | minus: 31536000 | date: "%Y-%m-%d" }}`
* "Only copy these tags": (use whatever order or product tag(s) you want to copy)
* "Remove those tags if a qualifying source cannot be found": yes
* "Run daily": yes

Note: the 31536000 value is a quantity of seconds; 31536000 is the number of seconds in a year. To adjust, replace this value with the number of seconds you want to use. For example, 30 days is 2592000 seconds.
Run this task to scan all of your customers and their order histories, copying order and/or product tags to the relevant customer. Optionally, configure a specific set of tags to look for, when scanning. Optionally, choose to remove those tags if a qualifying source can't be found.

Both the customer and order query options support Liquid. This means that you can dynamically query for orders, based on things like the current date.

For example, use these options to achieve customer tags that auto-expire a year after the newest qualifying order:

* "Only include orders matching this query": `created_at:>={{ "now - 1 year" | date: "%Y-%m-%d" }}`
* "Only copy these tags": (use whatever order or product tag(s) you want to copy)
* "Remove those tags if a qualifying source cannot be found": yes
* "Run daily": yes

**Important:** The customers query must use the **exact** casing and syntax as a query that is run from the customer segments admin screen. More information on the the syntax for these can be found [here](https://shopify.dev/docs/api/shopifyql/segment-query-language-reference).

For example, to only include customers that have the "subscriber", use this query: `customer_tags CONTAINS 'subscriber'`

## Installing this task

Expand Down
Loading

0 comments on commit 0dbea45

Please sign in to comment.