
Shopify Admin Customer Note Bulk Annotator
- 7 installs
- 173 repo stars
- Updated June 26, 2026
- 40rty-ai/shopify-admin-skills
shopify-admin-customer-note-bulk-annotator is a Claude Code skill that appends internal notes to Shopify customer records in bulk based on a filter query.
About
This skill queries Shopify customers matching a filter (such as a tag or spend threshold) and appends an internal note to each matching record. Internal notes are visible to staff but not customers, so teams use it for post-campaign flags, import annotations, or support context. It defaults to append mode and dry_run, and logs changes to a CSV.
- Appends an internal note to all customers matching a filter query in bulk
- Filters by tag, spend threshold, or email; append mode preserves existing notes
- Defaults to dry_run and logs before/after notes to a CSV
Shopify Admin Customer Note Bulk Annotator by the numbers
- 7 all-time installs (skills.sh)
- Ranked #1,587 of 2,715 Automation & Workflows skills by installs in the Skillselion catalog
- Data as of Aug 1, 2026 (Skillselion catalog sync)
shopify-admin-customer-note-bulk-annotator capabilities & compatibility
Free skill; requires an authenticated Shopify store session with read_customers and write_customers scopes.
- Capabilities
- bulk annotation · customer notes · bulk customer update · csv export
- Works with
- stripe
- Use cases
- data analysis
- Pricing
- Bring your own API key
What shopify-admin-customer-note-bulk-annotator says it does
Adds internal notes to customer records in bulk — useful for post-campaign flags, import annotations, or support context.
Internal notes are visible to staff in Shopify Admin but not to customers.
npx skills add https://github.com/40rty-ai/shopify-admin-skills --skill shopify-admin-customer-note-bulk-annotatorAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 7 |
|---|---|
| repo stars | ★ 173 |
| Last updated | June 26, 2026 |
| Repository | 40rty-ai/shopify-admin-skills ↗ |
What it does
Bulk-append an internal note to Shopify customers matching a tag, spend, or email filter for support context.
Who is it for?
Ops and support teams adding post-campaign flags, import source tags, or context notes to many customers at once.
Skip if: Notes visible to customers; these are internal staff-only notes, and replace mode can overwrite existing notes.
When should I use this skill?
You need to add the same internal note to every customer matching a filter.
What you get
Every customer matching the filter gets the note appended (or replaced), logged to an annotation CSV.
- Customer records with the note appended or replaced
- CSV annotation_log_<date>.csv of previous and new notes
By the numbers
- paginates customers 250 per request
- defaults append:true and dry_run:true
Files
Purpose
Queries customers matching a filter (tag, email list, or spend threshold) and appends a note to each customer record. Internal notes are visible to staff in Shopify Admin but not to customers. Used for post-campaign annotation, import source tracking, VIP flags, or support context.
Prerequisites
- Authenticated Shopify CLI session:
shopify store auth --store <domain> --scopes read_customers,write_customers - API scopes:
read_customers,write_customers
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| store | string | yes | — | Store domain (e.g., mystore.myshopify.com) |
| filter | string | yes | — | Customer filter query (e.g., tag:vip, total_spent:>=500) |
| note | string | yes | — | Note text to append to matching customers |
| append | bool | no | true | Append to existing note (true) or replace entirely (false) |
| dry_run | bool | no | true | Preview matching customers without executing mutations |
| format | string | no | human | Output format: human or json |
Safety
⚠️ Ifappend: false, this overwrites the existing customer note entirely. Existing notes will be lost. Default isappend: truewhich safely appends with a timestamp prefix. Run withdry_run: trueto confirm the customer list before committing.
Workflow Steps
1. OPERATION: customers — query Inputs: query: <filter>, first: 250, select id, displayName, note, pagination cursor Expected output: Matching customers with existing notes; paginate until hasNextPage: false
2. Construct new note: if append: true, prepend [YYYY-MM-DD] <note> to existing note (newline-separated); if append: false, replace with <note>
3. OPERATION: customerUpdate — mutation Inputs: id: <customer_id>, note: <new_note> Expected output: customer { id, note }, userErrors
GraphQL Operations
# customers:query — validated against api_version 2025-01
query CustomersByFilter($query: String!, $after: String) {
customers(first: 250, after: $after, query: $query) {
edges {
node {
id
displayName
defaultEmailAddress {
emailAddress
}
note
tags
}
}
pageInfo {
hasNextPage
endCursor
}
}
}# customerUpdate:mutation — validated against api_version 2025-01
mutation CustomerUpdateNote($input: CustomerInput!) {
customerUpdate(input: $input) {
customer {
id
displayName
note
}
userErrors {
field
message
}
}
}Session Tracking
Claude MUST emit the following output at each stage. This is mandatory.
On start, emit:
╔══════════════════════════════════════════════╗
║ SKILL: Customer Note Bulk Annotator ║
║ Store: <store domain> ║
║ Started: <YYYY-MM-DD HH:MM UTC> ║
╚══════════════════════════════════════════════╝After each step, emit:
[N/TOTAL] <QUERY|MUTATION> <OperationName>
→ Params: <brief summary of key inputs>
→ Result: <count or outcome>If dry_run: true, prefix every mutation step with [DRY RUN] and do not execute it.
On completion, emit:
For format: human (default):
══════════════════════════════════════════════
OUTCOME SUMMARY
Customers matched: <n>
Notes updated: <n>
Errors: <n>
Output: annotation_log_<date>.csv
══════════════════════════════════════════════For format: json, emit:
{
"skill": "customer-note-bulk-annotator",
"store": "<domain>",
"started_at": "<ISO8601>",
"dry_run": true,
"filter": "<query>",
"note": "<text>",
"append": true,
"outcome": {
"matched": 0,
"updated": 0,
"errors": 0,
"output_file": "annotation_log_<date>.csv"
}
}Output Format
CSV file annotation_log_<YYYY-MM-DD>.csv with columns: customer_id, name, email, previous_note, new_note
Error Handling
| Error | Cause | Recovery |
|---|---|---|
THROTTLED | API rate limit exceeded | Wait 2 seconds, retry up to 3 times |
userErrors on customerUpdate | Invalid input or read-only customer | Log error, skip customer, continue |
| No customers match filter | Filter too narrow | Exit with 0 matches |
Best Practices
- Always use
append: trueunless you explicitly intend to overwrite existing notes — staff notes may contain important history. - Include a datestamp in the
notetext itself (e.g.,"2026-04-11: Campaign X participant") so notes remain interpretable months later. - Use
dry_run: trueto confirm the customer count before annotating — a broad filter can match thousands of customers unexpectedly. - For import-source tracking, annotate immediately after the import run to maintain a clear audit trail.
Related skills
FAQ
Are these notes visible to customers?
No. Internal notes are visible to staff in Shopify Admin but not to customers.
Does it overwrite existing notes?
By default append:true prepends the new note with a timestamp and preserves existing notes; append:false replaces the note entirely and existing notes are lost.