I’ve recently noticed that ~80% of my 40k Shopify customer accounts seem to be spam and all follow the same format where the first name is their last name also. For example: Josephagomo Josephagomo, maryellenlb16 maryellenlb16. I don’t know where these came from as they are created separately over the course of several years, and Shopify doesn’t list a source for any of them. Regardless, I’d like to delete them, but I can’t seem to run a flow on existing customers, only new customers. I would love help here. Thanks!
Topic summary
A Shopify store owner has discovered approximately 30,000 spam customer accounts (80% of their 40k total accounts) that share a distinctive pattern: the first and last names are identical duplicates (e.g., “Josephagomo Josephagomo” or “maryellenlb16 maryellenlb16”).
Key details:
- These accounts were created gradually over several years
- Shopify doesn’t show a source for these accounts
- The owner wants to bulk delete them but has encountered a technical limitation
Current problem:
Shopify Flows can only be applied to new customers, not existing ones, preventing automated bulk deletion of the spam accounts.
The discussion remains open with no solution provided yet.
In Shopify Flow,
- Set Scheduled Time trigger
- Add Get Customer Data, Customers with no orders, set maximum of 100 customers
- Add For Each loop: Get Customer Data
- Add Condition: First Name equals Last Name
- Add Action: Delete Customer
Here are some screenshots
Hi @yonik. For your problem, you need to filter customers with first name and last name, and no orders. To delete those customers, you can do the following:
- Access to Shopify Flow.
- Set Scheduled time trigger.
- Add Get customer data:
- Set Maximum number of customers: 100.
- Customers with no orders (Get all customers who have created 0 orders).
- Add For each loop: Get customer data.
- Add Condition: First name equal to Last name.
- Add Action: Delete customer.
You cannot delete a customer if they have a past order, Shopify blocks that due to order-history retention.
In addition, Shopify has official docs to guide you on how to Delete customers in many different ways that you can refer to if you cannot apply the method I suggested: Delete customer.
Hope this helps ![]()
Hi Howie,
Thank you so much for this detailed response! I really appreciate it! I ran it as you said, and it seemed to run it once, and not properly iterate. Any ideas of how to fix this?
Thanks!
Yoni K
It looks like it’s the wrong item. Sorry there should be 2 that look the same but aren’t.
Make sure both say Foreachitem, not just item
Try that and see if it works
Also can you put up a screenshot of the workflow?
Thanks Howie!
I just edited it, and it actually deleted the problematic accounts! The only issue now is that it can only pull 100 accounts every 10 minutes, so it will take a long time for it to clean up all of the accounts. Additionally, I am worried that it might review the same accounts over and over again until the first 100 accounts it pulls each time are all valid, and then the flow becomes useless. How do i get it to only look at accounts it hasn’t previously looked at before?
Yeah I was thinking about that yesterday. Sooner or later, it’s going to look at 100 customers and they’re all going to be real customers and it’s gonna fail. In which case, you’ll have to change the sort by, make it descending, alphabetical, etc. Eventually, you might have to make a custom query. Maybe they came in batches at certain times of the month or something.
Play around with it for a bit. Instead of delete, you can add a customer tag or some non-abrasive action. A lot of the bots now are using the same address to test 100s of credit cards, so the Condition can be tweaked. You can do a lot with Flow, but it is temperamental and can be frustrating trying to find out why it’s not going through.
Yep, the usual way is to look at the customer and assign a tag, say “processed”.
The initial “Get customer data” should be modified to skip tagged customers, like this:
orders_count:0 AND tag_not:processed
Unfortunately, i think you can’t query for customers which has the same first and last name. The list of parameters, just in case, is here, under query – customers - GraphQL Admin
Another useful workflow is periodically deleting all customer tags from all customers, so customer data isn’t cluttered. Especially if you create lots of unnecessary tags.
Be SUPER careful here you applying a broad assumption to EVERY account.

John John, Lauren Lauren, etc are real names that happen.
You really need some other metric DO NOT apply a naive first == last therefore nuke.
Or have had prequalified the entire list by doing something like manually tagging them in a spreadsheet THEN delete based on the tag as a verification method.
→ or order total value ←
Having a tag also means subsequent queries become smaller and smaller as illegitimate accounts are deleted.
e.g. Falsehoods Programmers Believe About Names | Kalzumeus Software.
#19. People’s first names and last names are, by necessity, different.
First middle and last can all be the same either legally or that’s what the customer wants.
Erroneously deleting customers can be a financial or legal RISK.
Think it through before pulling the trigger.
You might want to use a more featureful automation tool.
Mechanic has a trial, or a pay what feels good pricing
The library has a delete task when new orderless accounts are created .
That could be modified to be manually triggerable to send accounts in bulk to it.
Actually I’ll dig around and see if that exists somewhere.
There is no risk in deleting any customer beyond potential future revenue. The only customers you can delete are ones whom you have no legal obligation in the first place. E.g. signed up to email, abandoned checkout, etc. Shopify prevents customers who have made an order from being deleted.
A lack of an order is not a measure of obligation, nor are shopify’s safe gaurds the same as a business obligations nor all encompassing in protecting such things.
B2B may have accounts that don’t place orders but are part of agreements.
Importing existing customers without orders associated yet.
A customer can be unlinked from an order for various reasons , etc etc etc etc.
Approach such assumptions with caution where several others peoples money is involved.
Sure, if you got some contracts or something like that with someone, and they don’t make official orders. I can dig it. I’ll amend. Just be aware of your situation before doing so.
Too right
@yonik if flow isn’t getting it done here’s a sample script for mechanic hodgepodged from a couple different tasks.
Testing and fixes left to the reader, I only made this because I noticed there’s not a good BULK starting point as normally you can ony send 50 resources at a time to mechanic|apps from the shopify admin.
Please look for foot guns as I have not tested the logic end to end and this isn’t doing any other checks besides customer.firstName == customer.lastName but it does have boilerplate for using tags as speedbumbs.
Subscriptions - Mechanic App - Nuke Customer Accounts - Bulk Query Operation
subs:
mechanic/user/trigger
mechanic/shopify/bulk_operation
This queries in bulk then uses REST delete
Script - Mechanic App - Nuke Customer Accounts - Bulk Query Operation
{% comment %} 2025 PaulN - this is as is , review and think ahead before using{% endcomment %}
{% comment %}subs:
mechanic/user/trigger
mechanic/shopify/bulk_operation{% endcomment %}
{% assign customers = array %}
{% if event.topic contains "shopify/customers/" %}
{% if event.preview %}
{% assign customer = hash %}
{% assign customer["admin_graphql_api_id"] = "gid://shopify/Customer/1234567890" %}
{% assign customer["tags"] = "" %}
{% endif %}
{% assign customer_node = hash %}
{% assign customer_node["id"] = customer.admin_graphql_api_id %}
{% assign customer_node["tags"] = customer.tags | split: ", " %}
{% assign customers[0] = customer_node %}
{% elsif event.topic == "mechanic/user/trigger" %}
{% capture bulk_operation_query %}
query {
customers {
edges {
node {
id
firstName
lastName
tags
}
}
}
}
{% 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 %}
{"id":"gid://shopify/Customer/1234567890","tags": []}
{% endcapture %}
{% assign bulkOperation = hash %}
{% assign bulkOperation["objects"] = objects_jsonl | parse_jsonl %}
{% endif %}
{% assign customers = bulkOperation.objects %}
{% endif %}
{% for customer in customers %}
{%- comment -%}⚠⚠RUBBER MEETS THE ROAD{%- endcomment -%}
{% assign delete_customer = false %}
{% if customer.firstName == customer.lastName %}
{% assign delete_customer = true %}
{% endif %}
{% assign add_tag = false %}
{% assign remove_tag = false %}
{% if customer.tags contains options.customer_tag_to_watch__required %}
{% if customer.tags contains options.customer_tag_to_use_when_missing__required %}
{% assign remove_tag = true %}
{% endif %}
{% else %}
{% unless customer.tags contains options.customer_tag_to_use_when_missing__required %}
{% assign add_tag = true %}
{% endunless %}
{% endif %}
{% if add_tag or remove_tag %}
{% action "shopify" %}
mutation {
tags{% if add_tag %}Add{% else %}Remove{% endif %}(
id: {{ customer.id | json }}
tags: {{ options.customer_tag_to_use_when_missing__required | json }}
) {
userErrors {
field
message
}
}
}
{% endaction %}
{% endif %}
{% if options.ignore_customers_having_this_tag != blank %}
{% assign customer_tags = customer.tags | split: ", " %}
{% if customer_tags contains options.ignore_customers_having_this_tag %}
{% log "Customer had a whitelisted tag; ignoring" %}
{% assign delete_customer = false %}
{% endif %}
{% endif %}
{%- comment -%}⚠ This is using the REST api?? So may need updating{%- endcomment -%}
{% if event.preview or delete_customer %}
{% action "shopify" %}
[
"delete",
["customer", {{ customer.id | json }}]
]
{% endaction %}
{% endif %}
{% endfor %}
i’ve got a custom gif of that for this stuff somewhere but can never find the darn thing!!
Hey,you can use Customers segment to filter the customers who haven’t purchanse , and delete them manually. pls refer to the below
:
Right, but Customer segments are not that flexible, though they do have info not available elsewhere.
Say, you can’t check firstName == lastName in segments.
However, one can start a Flow on “Customer joined a segment” trigger.














