shopify-admin-marketing-consent-report

SkillCommunication

Read-only: audits email and SMS marketing consent status across the customer base for compliance and segmentation.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the shopify-admin-marketing-consent-report skill

What this skill tells your AI

The instructions your AI receives, as published by 40rty-ai/shopify-admin-skills in skills/customer-ops/shopify-admin-marketing-consent-report/SKILL.md and read by ahel’s review.

Purpose

Scans all customer records and reports the breakdown of email and SMS marketing consent status (subscribed, unsubscribed, pending, never asked). Used for compliance audits, GDPR/CAN-SPAM reviews, and understanding the addressable marketing audience. Read-only — no mutations.

Prerequisites

  • Authenticated Shopify CLI session: shopify store auth --store <domain> --scopes read_customers
  • API scopes: read_customers

Parameters

ParameterTypeRequiredDefaultDescription
storestringyesStore domain (e.g., mystore.myshopify.com)
channelstringnobothConsent channel to audit: email, sms, or both
formatstringnohumanOutput format: human or json

Safety

ℹ️ Read-only skill — no mutations are executed. Safe to run at any time.

Workflow Steps

  1. OPERATION: customers — query Inputs: first: 250, select emailMarketingConsent { marketingState, consentUpdatedAt }, smsMarketingConsent { marketingState, consentUpdatedAt }, pagination cursor Expected output: All customers with consent states; paginate until hasNextPage: false

  2. Count customers by consent state for each channel

  3. Calculate: addressable audience (subscribed), at-risk (pending), unreachable (unsubscribed/not asked)

GraphQL Operations

# customers:query — validated against api_version 2025-01
query MarketingConsentAudit($after: String) {
  customers(first: 250, after: $after) {
    edges {
      node {
        id
        displayName
        defaultEmailAddress {
          emailAddress
        }
        emailMarketingConsent {
          marketingState
          consentUpdatedAt
          marketingOptInLevel
        }
        smsMarketingConsent {
          marketingState
          consentUpdatedAt
        }
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}

Session Tracking

Claude MUST emit the following output at each stage. This is mandatory.

On start, emit:

╔══════════════════════════════════════════════╗
║  SKILL: Marketing Consent Report             ║
║  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>

On completion, emit:

For format: human (default):

══════════════════════════════════════════════
MARKETING CONSENT REPORT
  Total customers: <n>

  Email Marketing:
    Subscribed:    <n>  (<pct>%)  ← addressable
    Unsubscribed:  <n>  (<pct>%)
    Pending:       <n>  (<pct>%)
    Not asked:     <n>  (<pct>%)

  SMS Marketing:
    Subscribed:    <n>  (<pct>%)
    Unsubscribed:  <n>  (<pct>%)
    Not asked:     <n>  (<pct>%)
  Output: consent_audit_<date>.csv
══════════════════════════════════════════════

For format: json, emit:

{
  "skill": "marketing-consent-report",
  "store": "<domain>",
  "total_customers": 0,
  "email": { "subscribed": 0, "unsubscribed": 0, "pending": 0, "not_asked": 0 },
  "sms": { "subscribed": 0, "unsubscribed": 0, "not_asked": 0 },
  "output_file": "consent_audit_<date>.csv"
}

Output Format

CSV file consent_audit_<YYYY-MM-DD>.csv with columns: customer_id, email, email_marketing_state, email_consent_updated_at, sms_marketing_state, sms_consent_updated_at

Error Handling

ErrorCauseRecovery
THROTTLEDAPI rate limit exceededWait 2 seconds, retry up to 3 times
No customersEmpty storeExit with 0 results

Best Practices

  • "Subscribed" is your addressable marketing audience — a low subscription rate may indicate checkout opt-in is not prominent enough.
  • "Pending" means a customer provided their email but has not confirmed consent — this is common for double opt-in flows.
  • Run before major campaigns to get an accurate count of the addressable audience; your ESP will show a different number if it has additional unsubscribes not synced back to Shopify.
  • GDPR compliance note: customers in the EU with marketingOptInLevel: SINGLE_OPT_IN may require a re-consent campaign depending on your legal basis for processing.

Signals

GitHub stars
187
Forks
18
Last commit
Aug 2026

ahel review

  • S4info
    community integration — published by 40rty-ai, not shopify

Automated review, not a security audit. Ruleset v1.

Advanced
Catalog kind
skill
Gateway key
shopify-admin-marketing-consent-report
Source
github.com/40rty-ai/shopify-admin-skills