Tracking Update Bulk

Batch-update tracking numbers and URLs on existing fulfillments when a carrier reassigns tracking IDs.

shopify-admin-tracking-update-bulk


Purpose

Looks up existing fulfillments on orders and updates their tracking numbers and carrier URLs in bulk. Used when a carrier reissues tracking IDs after a label reprint, a 3PL batch-uploads corrected tracking, or a carrier integration pushes wrong tracking numbers. Replaces manual tracking corrections in Shopify Admin order by order.


Prerequisites

  • Authenticated Shopify CLI session: shopify store auth --store --scopes read_orders,write_fulfillments
  • API scopes: read_orders, write_fulfillments

  • Parameters


    ParameterTypeRequiredDefaultDescription
    storestringyesStore domain (e.g., mystore.myshopify.com)
    updatesarrayyesList of {order_id, fulfillment_id, tracking_number, tracking_url, carrier} objects
    notify_customerboolnofalseResend shipping confirmation with updated tracking
    dry_runboolnotruePreview updates without executing mutations
    formatstringnohumanOutput format: human or json

    Safety


    > ⚠️ fulfillmentUpdate overwrites existing tracking info. Set notify_customer: false unless you explicitly want to resend shipment notifications — customers will receive a new email for every updated fulfillment if enabled. Run with dry_run: true to confirm the fulfillment list before committing.


    Workflow Steps


  • OPERATION: order — query
  • Inputs: id: for each order in updates

    Expected output: Order with fulfillments { id, trackingInfo } to confirm existing fulfillment IDs match


  • OPERATION: fulfillmentUpdate — mutation
  • Inputs: fulfillmentId: , trackingInfoUpdateInput: { company, number, url }, notifyCustomer

    Expected output: fulfillment { id, trackingInfo }, userErrors


    GraphQL Operations


    # order:query — validated against api_version 2025-01
    query OrderFulfillments($id: ID!) {
      order(id: $id) {
        id
        name
        fulfillments {
          id
          status
          trackingInfo {
            company
            number
            url
          }
        }
      }
    }
    

    # fulfillmentUpdate:mutation — validated against api_version 2025-01
    mutation FulfillmentUpdate($fulfillmentId: ID!, $trackingInfoInput: FulfillmentTrackingInput!, $notifyCustomer: Boolean) {
      fulfillmentUpdate(
        fulfillmentId: $fulfillmentId
        trackingInfoUpdateInput: $trackingInfoInput
        notifyCustomer: $notifyCustomer
      ) {
        fulfillment {
          id
          status
          trackingInfo {
            company
            number
            url
          }
        }
        userErrors {
          field
          message
        }
      }
    }
    

    Session Tracking


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


    On start, emit:

    ╔══════════════════════════════════════════════╗
    ║  SKILL: Tracking Update Bulk                 ║
    ║  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
      Fulfillments targeted:   <n>
      Tracking numbers updated: <n>
      Notifications sent:       <n>
      Errors:                   <n>
      Output:                   tracking_update_<date>.csv
    ══════════════════════════════════════════════
    

    For format: json, emit:

    {
      "skill": "tracking-update-bulk",
      "store": "<domain>",
      "started_at": "<ISO8601>",
      "completed_at": "<ISO8601>",
      "dry_run": true,
      "outcome": {
        "targeted": 0,
        "updated": 0,
        "notifications_sent": 0,
        "errors": 0,
        "output_file": "tracking_update_<date>.csv"
      }
    }
    

    Output Format

    CSV file tracking_update_.csv with columns:

    order_name, fulfillment_id, old_tracking_number, new_tracking_number, carrier, notify_customer, status


    Error Handling

    ErrorCauseRecovery
    THROTTLEDAPI rate limit exceededWait 2 seconds, retry up to 3 times
    userErrors on fulfillmentUpdateFulfillment cancelled or not foundLog error, skip, continue
    Fulfillment ID not on orderStale ID in updates listLog mismatch, skip, continue

    Best Practices

  • Keep notify_customer: false unless the carrier is tracking a replacement shipment — customers find repeated shipping emails confusing and may open unnecessary support tickets.
  • Provide fulfillment_id directly in the updates input when possible to skip the order lookup step entirely.
  • For 3PL integrations that send corrected tracking via CSV, parse the CSV into the updates array before running this skill.