Shopify product-data import is complete only when every changed row has an identity, an owner, an expected result, and an evidence trail. A green upload notice is not proof that a handle matched the intended product, that variant values were preserved, or that a media URL was attached to the right object. This article treats 9916 as a one-time or explicitly operator-triggered catalog load. It covers a CSV file, a bounded Admin GraphQL batch, field validation, failure isolation, and a verifiable recovery point. It does not turn a product import into a permanent synchronization service.
Write the batch contract before editing a row: file version, checksum, store timezone, owner, sample, permitted columns, prohibited columns, and reviewer. Products, variants, media, prices, inventory, markets, and search fields may appear together in a source file, but they do not share one identity key or one owner. When a value has no traceable source, mark it for review instead of inventing a default.
1. Classify the job: one-time load or ongoing synchronization
The manual-trigger boundary of 9916
A one-time load has a visible beginning and end. An operator prepares a fixed file or a bounded API input, reviews a preview, approves the permitted fields, runs the batch, samples the result, reconciles the differences, and closes the record. The file name, checksum, sample rows, time window, operator, and error list form its evidence. Running a new, explicitly approved repair file later does not make it a scheduler; it is a new bounded batch.
This scope includes a migration from another platform, a seasonal catalog refresh, and a small release of new SKUs. It can include a read-back check for inventory fields or image URLs, but those checks do not create a fulfillment workflow, a media-creative plan, or an accounting ledger. Each field still needs a declared overwrite rule and an owner.
When recurring demand belongs to 9917
Phrases such as “pull every night,” “push every external change,” “replay a webhook,” or “resolve simultaneous edits” describe recurring synchronization. That work needs scheduling, cursors, retries, idempotency, source-of-truth ownership, and conflict policy. It should be read in the 9917 product data synchronization guide, while this page records only the stop condition and required inputs.
An Admin GraphQL mutation is not automatically a synchronization service. productSet can create or update products in one controlled operation, but it does not supply an external cursor, long-term scheduler, replay policy, or conflict owner. Judge the boundary by the operating contract, not by the API name. Without continuing events and ownership rules, use the one-time batch acceptance model.
2. Export first and establish a recoverable work point
Export the catalog, source file, and checksum
Before changing a row, export the current catalog or obtain an approved baseline. Keep the original export read-only. Store the cleaned file, field mapping, sample results, and errors separately. Record a SHA-256 checksum, byte count, creation time, store timezone, operator, and tool version for each file. Avoid names such as “final,” which encourage silent overwrites. Shopify documents backing up before import and testing a small subset or development store.
A backup is useful only when its contents are explainable. Sample stable identity records and retain the handle, SKU, variant, price, inventory location, and publication state where each is in scope. If a value cannot be exported, record that gap. After import, a missing collection member can then be investigated as a source omission, mapping error, or platform result instead of being attributed to “CSV” in general.
A recovery point is not an automatic platform undo
Shopify’s import guidance states that an import cannot be cancelled after it starts and does not promise a complete historical restore mechanism. In this article, “recoverable” means an operator can identify the pre-change values, retain the input, isolate failed rows, and prepare a narrowly approved repair or reverse patch followed by verification. It does not mean a one-click undo, an all-object transaction, or a guaranteed rollback supplied by Shopify.
Recovery material should contain the original export, cleaned input, field matrix, permitted columns, preview, success and failure identifiers, operator record, and before/after diff. If the batch was approved to change only title and description, a reverse patch must not be a full-field overwrite. A column whose old value cannot be proven is a stop condition, not an invitation to write an empty value.
| Risk case | Pre-import evidence | Stop gate | Recovery preparation |
|---|---|---|---|
| Handle points to the wrong product | Handle/SKU sample | An identity key is not unique | Freeze the file and retain the old export |
| Variant count differs | Product-to-variant list | An option or SKU is missing | Isolate that product’s rows |
| Image URL fails | URL, source row, expected order | A required media item cannot be checked | Isolate media rows |
| Price or inventory is abnormal | Amount, unit, location baseline | The value or unit is unexplained | Stop numeric overwrite and compare the baseline |
| Result cannot reconcile | Preview and result sample | Processed rows cannot be accounted for | Keep verified rows and create a separate patch |
3. Build the field dictionary and stable identity
Responsibilities of handle, title, SKU, and variant ID
handle participates in the product identity and public URL context. title is a reader-facing name. A SKU is commonly used by an operations or inventory system to identify a product or variant. These values are not interchangeable. A matching title does not prove that two products are the same, and an external row number is not a Shopify resource ID. When a platform resource ID is available, keep it as result evidence rather than replacing it with a spreadsheet index.
Choose the update key before generating the file. It might be a verified handle, an internal SKU that resolves to one product, or a stored resource ID. Define separate actions for no match, one match, and multiple matches. Keep the old key and new value together. Changing the handle first can make the old record impossible to find with the original lookup.
Conflict checks for create and update rows
Create rows need a check that the identity is complete and does not collide with the catalog. Update rows need a check that the matched object is correct and that every overwrite is approved. Separate product-level, variant-level, media, and location columns in the field matrix. If one row mixes all four scopes, model the responsibilities before loading it. Multiple rows for one handle with contradictory titles, vendors, or SKUs must fail deterministically; row order is not a conflict policy.
| Field group | Owner | Pre-import check | Post-import evidence | Failure action |
|---|---|---|---|---|
| Product identity | Catalog owner | Unique handle, title, and internal key | Product ID and handle query | Isolate the identity conflict |
| Variant identity | Product operations | Unique option combination and SKU | Variant list sample | Do not overwrite the whole group |
| Text | Editorial/localization owner | Encoding, language, and empty-value rule | Field-level title/description diff | Return the text row |
| Commercial numbers | Approved operator | Currency, unit, and precision | Price/weight sample | Stop numeric overwrite |
| Media | Content owner and URL owner | URL, row relationship, and order | Media result and failures | Repair media separately |
| Inventory | Inventory owner | Location, unit, and snapshot time | Location-level result | Use the inventory workflow |
4. Organize product, variant, and image rows
Relationships among first, variant, and image rows
Use the structure in Shopify’s official CSV guide rather than inferring the meaning of blank cells. A product’s first row carries its title, handle, and product-level fields. Variant rows express option combinations and variant-level values. Image rows add media relationships. A product spanning several rows needs a tested rule for order and blank fields; do not assume that a blank title always means “continue the previous product” unless the current template explicitly defines it.
Put product images, variant images, and their relationships in the field dictionary. A reachable URL does not prove that it was attached correctly, that its order is correct, or that its alt text and channel display are right. Retain the source row number, handle, variant relationship, and expected order for every media row. This allows a media-only patch if the product fields pass and the media does not.
Empty rows, duplicates, order, and readability
Remove accidental blank rows and verify a unique header, consistent column count, complete product first rows, non-duplicated option combinations, and image rows inside the right product scope. Use a deterministic parser and then read representative samples manually. Keep the original file separate from the normalized file. A spreadsheet application must not silently trim leading zeros, reformat dates, reorder rows, or alter URL encoding.
The objective is reproducibility, not cosmetic alignment. SKUs, barcodes, and handles may need text treatment. Prices and weights need explicit units. Multilingual text must not become replacement characters. If the structure is wrong, repair the generator or template and regenerate the batch instead of making untracked edits in an import screen.
| Row type | Primary role | Required relationship | Typical fault | Isolation scope |
|---|---|---|---|---|
| Product first row | Establish product and product fields | Handle, title, and product key | Empty title or duplicate handle | One product |
| Variant row | Express options and variant values | Product, option combination, SKU | Duplicate combination or missing price | Variant group |
| Image row | Attach a media URL | Product/variant and expected order | Unreachable or misbound URL | Media rows |
| Delimiter/empty row | Preserve file readability | Must not change parser boundaries | Hidden character or extra column | File |
| New product first row | Begin the next product scope | Previous fields must not leak | Serial handle or shifted columns | Current batch |
5. Small-batch rehearsal: prove the path before scaling
Select a development store or representative sample
Choose a sample that exposes risk, not only the easiest row. Include a new product, an update, a product with several variants, a product with multiple images, text with special characters, and a product whose inventory fields name a location. If a development store is available, test there first. If the target store must be used, keep the set to an approved handful of SKUs and record the observation window.
The sample does not prove that the whole file will succeed. It reveals template, permission, field, and result-interpretation problems. For every sample, retain the expected value, observed value, error, evidence, and next action. An unexplained identity, currency, media, or publication difference is a reason not to add the remaining rows to that run.
Preview, approve, and sample the result
Follow Shopify’s upload, review, and import sequence and read the preview before approval. The reviewer should ask whether each column is permitted, what an empty value means, whether the handle matches the intended object, and whether variants and images are related. Approval is not a row-count check. Associate the preview, approver, approval time, original checksum, and actual run checksum in the batch record.
Sample immediately after the operation. Include successful and failed rows, boundary characters, a product without media, and a multi-variant product. “Successful” in a processing result is only a processing signal; read the objects back and inspect the page or channel result where required. Define a scaling gate in the batch record. If it is not met, retain the verified small batch and stop.
6. Text fields, classification fields, and language variants
Empty-value rules for title, description, vendor, tags, and type
Check language, encoding, empty values, length, and safe rendering for text fields. The title should match the approved product identity. Description line breaks, lists, and links need a rendered sample. Vendor, tags, and product type should use an approved vocabulary or an explicit human review. Do not use tags as a substitute for taxonomy, and do not copy one marketing paragraph across the entire catalog. Distinguish an intentionally empty description from a source omission.
When a product has Chinese and English values, keep source and destination columns separate and record the content version and editor. Do not use an import file to invent specifications, certifications, stock promises, or market eligibility. Import is responsible for transporting an approved value; content, localization, and compliance owners remain responsible for whether that value is fit to publish.
Transport validation is not taxonomy design
A file may contain product category, product type, collection, and navigation columns, but accepted fields do not prove that the classification system is well designed. 9916 checks column names, value format, product-to-collection result, and failure rows. Hierarchy, naming, filters, navigation, and taxonomy SEO belong to the 9922 product classification and collection guide. If there is no approved vocabulary, isolate unknown values instead of creating a new taxonomy during import.
Rule-based collections may recalculate after a load, so record the load time, collection condition, and sample result. One product appearing in a collection does not prove that every related product is correct. A product temporarily missing does not by itself prove that the CSV failed. Read the product fields, collection result, and navigation presentation as separate acceptance layers.
7. Price, SKU, inventory, and location semantics
Verify amount, weight, unit, and precision
A price is not safe merely because it parses as a number. The matrix should state currency, tax-inclusion assumption, rounding, discount treatment, and decimal precision. If the store rule or source evidence does not settle one of those questions, perform a format check and stop short of a financial conclusion. Weight likewise needs a unit and precision; pounds, kilograms, and grams cannot share an unlabeled column.
Keep leading zeros in SKUs and barcodes. Before import, count empty, duplicate, and malformed values. After import, sample at both product and variant level. A changed catalog price does not describe an order’s historical price or an accounting result. This page transports and verifies catalog fields; it does not decide payment, tax, or finance policy.
Product import is not an inventory transfer or ledger
Inventory fields need a location, quantity meaning, availability rule, snapshot time, and owner. An accepted product row does not prove that stock moved between locations, that fulfillment is ready, or that an inventory ledger has reconciled. For a location movement, use the separate Shopify inventory transfer documentation. 9916 records the import sample and result only.
If inventory differs from expectation, freeze subsequent rows and separate product-property success, inventory-field failure, and an incomplete location operation. Do not use a reverse product CSV as a substitute for an inventory transfer. The inventory owner verifies quantities and locations; product operations verifies SKUs and variants; the record preserves both timestamps.
| Acceptance object | Record | Pass condition | Do not infer |
|---|---|---|---|
| SKU/barcode | Original value, leading zeros, variant | Unique and readable | Inventory is correct |
| Price | Amount, currency, precision, time | Matches approved matrix | Tax or order amount |
| Weight | Amount, unit, variant | Unit is explicit and readable | Shipping or packaging cost |
| Location inventory | Location, quantity, time, owner | Sample matches authorized baseline | Transfer or fulfillment is complete |
| Variant option | Name, combination, SKU | Combination is not duplicated | Order history changed |
8. Image URLs, media relationships, and failure isolation
Record URL, relationship, order, and alt text
Preflight an image URL for its protocol, host, reachability, file type, product relationship, and variant relationship. Passing that check does not prove that Shopify fetched the asset or that the page renders it in the intended order. Retain the platform result, media order, and a rendered sample. Do not equate an import pass with image compression, creative quality, or image SEO performance; those are separate media acceptance tasks.
For every product, keep an expected list of the primary image, additional images, variant association, and alt text. A temporary signature, access policy, or redirect may expire between preflight and import, so record the check time and failure reason. An unstable URL belongs in an isolation list, not in a broad rerun.
Isolate a product batch when media fails
If product fields pass and media fails, preserve the successful read-back and mark the media rows rather than rerunning the catalog. Confirm that the failed row did not change the product identity, then create a media-only patch. If a shared host fails for several products, stop the related group; if one URL fails, repair its source and repeat a small media sample.
Missing media can affect page review, but it does not prove that a product is out of stock, unpublished, or guaranteed to lose search performance. Record product, media, channel display, and search observations separately. For photography, compression, alt text systems, and performance, use the 9921 product-image guide, not this import page.
9. Status, markets, collections, and publication results
Verify draft or publish intent separately
Processing a CSV does not by itself establish a product’s status, channel, or market visibility. Shopify’s Product documentation distinguishes product fields, status, and publication information, so the matrix should keep target state, target market/channel, and observed state in different columns. In a small batch, test one product intended to stay a draft and one product that has an approved visibility state. This prevents test content from becoming public by accident.
Record the approver, time, channel, and test account for a status change. If a channel does not show a product, check eligibility, publication settings, and read-back data before adding more changes. Markets, languages, currencies, and localized URLs have their own configuration. Product import proves only the transported fields, not a complete store launch.
Record collection results without redesigning taxonomy
When a file includes collection or type columns, test a fixed product sample after import: was the value retained, did a rule-based collection recalculate, and does the page show the expected label and link? Record the observation time and refresh condition. Do not change a global collection rule merely to make one sample appear; that turns data loading into taxonomy governance.
Split anomalies by object: product, variant, media, publication, collection, and navigation each need a result line, owner, and stop gate. The final batch record may summarize them, but one layer must not be used as proof for another.
10. File format, size, and the pre-import gate
UTF-8, LF, headers, and the 15 MB limit
Use Shopify’s documented checks for UTF-8 encoding, LF line endings, unique headers, consistent column counts, and file size. The product-import guide documents a 15 MB file limit. Treat it as an operational gate and split a file near the limit instead of relying on compression or an upload screen that appears to accept it. Measure bytes; character count is not file size.
Inspect the first and last rows, quoting, commas, embedded newlines, hidden characters, empty columns, and unusually long text. Keep an original byte copy and generate a normalized copy separately; calculate a new checksum after normalization. If a spreadsheet application opened the file, repeat the leading-zero, date, encoding, line-ending, and URL checks before use.
Prevent spreadsheet tools from damaging source structure
Keep a read-only source area and a reproducible generation area. Generate the column order and escaping from the field dictionary, then run an independent parser for row count, column count, and identity samples. Manual review is valuable but must not be the only change record. Express repairs as rules or small patch files so that a known file can be recreated.
Do not enter the admin import when the format gate fails. Shopify’s common import-issues page is a diagnostic entry point, not proof that semantic data, media access, inventory, or publication is correct. Classify format failure, data failure, and platform-processing failure separately; each has a different next action.
| Preflight item | Check | Evidence | Stop condition |
|---|---|---|---|
| Original file | Keep read-only copy and checksum | File name, bytes, hash | Hash cannot be reproduced |
| Encoding/line endings | Parse UTF-8 and LF independently | Encoding and line-ending report | Replacement characters or mixed endings |
| Headers/columns | Compare with approved template | Column list and error rows | Missing, duplicate, or extra column |
| Size | Read file bytes | Byte count and documented gate | Over 15 MB or near limit without a split |
| Identity sample | Compare handle/SKU/variant | Expected-versus-observed table | Empty, duplicate, or colliding object |
| Recovery material | Check export, mapping, repair plan | Directory inventory | Approved fields cannot be restored |
11. CSV runbook: upload, preview, approve, and accept
Make one batch observable from start to finish
First freeze scope: a product ID or SKU set, permitted fields, file checksum, operator, and time window. Second, export the baseline and create a sample. Third, run local format and identity checks. Fourth, upload to a development store or limited sample and read the preview. Fifth, approve columns and state. Sixth, run the import and save activity evidence. Seventh, read the results back, reconcile fields, sample media and collection/channel outcomes, and classify errors.
Each step has a continue or stop signal. Upload success permits review; review success permits approval; approval does not eliminate the rehearsal; process completion does not eliminate read-back. Do not modify the source file and admin settings at the same time, because that hides causality. Close one batch before starting another.
Record activity evidence, errors, owner, and stop point
Record start and finish time, file name and checksum, scope, operator, approver, platform messages, success and failure counts, failed rows, read-back sample, and next action. Shopify activity messages may be one piece of evidence, but they do not replace field-level reconciliation. If the interface has no complete history, the team’s batch record is the traceable layer.
Keep the original error text and add a team category: format, identity, value, media, permission, state, collection, or unknown. Do not treat an error sentence as a guaranteed fix. Isolate failed rows, create a new input and checksum after repair, and never overwrite the only copy of the file that produced the result.
12. A controlled Admin GraphQL alternative
Responsibility split between productCreate and productUpdate
The official Admin GraphQL documentation separates productCreate and productUpdate. Product creation requires the documented write_products permission and has its own initial-variant behavior; later variant work is a separate boundary. Product updates change product fields, but should not be read as an automatic update of every variant. A controlled batch must record API version, permission, input, returned errors, and resource state.
GraphQL is useful when the structure is stable and the team needs explicit field selection and resource IDs. It is not a universal CSV replacement or a multi-object transaction. After a response without an error, query products, variants, media, and publication state as required. A successful request says that the request was accepted; it does not say that every downstream object has the intended value.
Deletion and partial-update risks in productSet and bulk variants
productSet supports product create/update and synchronous or asynchronous operation modes. Its documented omission rules matter: an omitted list field may be deleted, while other omitted fields have different retention behavior. productVariantsBulkUpdate has partial-update semantics and a documented variant limit. Put each list field in the matrix and label the intent as preserve, replace, or clear. Never infer safe behavior from one successful response.
Partial update does not mean atomic rollback. Preserve pre-change values for products, variants, and media; keep batches bounded; read returned user errors and result objects; and stop a related request group when an error is not understood. Re-open the current API documentation before use because version, plan, and limit details change.
13. Throttling, asynchronous bulk work, and retry limits
Completion evidence for an asynchronous bulk query
An Admin GraphQL bulk query is asynchronous. Submission, waiting, obtaining the result, and using it to generate a new input are four separate stages. Keep the operation ID, submission time, state changes, errors, download retention rule, and result checksum. A completed state does not prove that every field satisfies the dictionary or that the storefront immediately shows the value. Check record count, empty values, and fixed samples first.
When a bulk result creates another CSV, retain the relationship between the read version and write version. Do not use an old file as though it were a new result after a read failure, and do not load an incomplete download. A task that exceeds the team’s waiting window becomes a diagnostic stop, not an unbounded retry loop or a duplicate task.
Query cost, input arrays, and backoff records
Shopify’s API limits documentation explains calculated query cost and leaky-bucket behavior, with examples of query and input limits. The actual limit depends on API version, plan, query shape, and response cost. Record cost, response extensions, throttle signals, and backoff time for each run. Retries need a count, delay, and a decision that the operation is safe to repeat; exponential backoff is not a guarantee of success.
Split inputs by stable identity so that one product cannot enter two requests at once. After a timeout or throttle, determine whether the server processed the request before retrying. An uncertain result is a stop: inspect the operation, count the unverified range, and issue a small approved patch only after the state is known.
14. Result validation, diagnosis, and failure isolation
Before/after field diff and sample reconciliation
Acceptance has three layers. The first is structure: the file parses, row counts agree, identity keys are unique, and requests expose no unhandled errors. The second is object state: products, variants, media, price, inventory, status, and collection results match the approved matrix. The third is a page or channel sample: title, options, images, visibility, and links match expectations. Save old value, new value, comparison rule, and owner for each layer.
Classify a diff as missing, emptied, normalized, approved, or unauthorized. A different display precision may be formatting; a different price may be a high-risk change. Do not hide one severe anomaly behind a high aggregate success rate. Match the sample first by product identity, then by variant option, then by field. Match media by URL and relationship, inventory by location and time, and state by approval record.
Split repair batches by error class
The smallest safe isolation unit may be a product, a variant group, a media row, or a field column, depending on how far the error can propagate. Isolate a product for identity conflict, media for a failed host, and the whole file for an encoding error. For throttling, isolate requests whose server-side state is still unknown. Every isolated unit needs the original error, repair action, new checksum, and re-acceptance result.
Never put an unverified success row into a repair batch. Keep accepted rows read-only, generate a minimal patch from the diff, and check that the current state still matches the old baseline before running it. If a human changed the record meanwhile, obtain a new baseline. A smaller repair can take longer, but it limits overwrite scope and makes the result explainable.
| Signal | Evidence | Action | Continue when |
|---|---|---|---|
| Header error | Parser error and file row | Repair template and checksum | Structure checks pass |
| Handle mismatch | Lookup result and identity table | Isolate the row | One object is confirmed |
| Partial variant failure | User error and variant read-back | Split by variant group | Every combination is explained |
| Unavailable image | URL and media result | Repair media separately | Product body passed |
| Throttle or timeout | Cost, state, and timing | Pause and establish server state | Unverified requests are counted |
| Unauthorized field change | Before/after diff | Stop and restore approved scope | Owner re-approves |
15. Acceptance, recovery, and in-scope internal navigation
Completion definition and recovery materials for 9916
A 9916 batch is complete only when its original export and input checksum are reproducible, preview and approval exist, identity keys are unique, permitted fields pass, media and state samples pass, collection and channel outcomes are separately recorded, errors are isolated or closed, the before/after diff has an owner’s approval, and recovery materials are readable. “Not checked” must not be reported as pass.
Recovery is not a blind overwrite of every old value. Identify the field, old value, and current value, then create the smallest reverse patch that is approved. Read the object back and compare it after the patch. If an old value or platform state cannot be proven, stop for a human decision. A CSV, GraphQL response, webhook, or activity message is not a complete transaction history on its own.
Boundary reading for 9917, 9921, 9922, 5946, and 9746
For recurring external sync, delta cursors, webhook retry, and multi-system conflict rules, read the 9917 product synchronization article. For photography, compression, alt text, media SEO, and performance, read the 9921 product-image article. For taxonomy hierarchy, collection rules, navigation, and classification SEO, read the 9922 classification article. For whole-store product, payment, shipping, and launch sequencing, read the 5946 store-launch article. For gift-card issuance, refunds, currencies, security, and finance, read the 9746 gift-card article. These are same-language navigation links, not evidence for this article, and they do not change the one-time import boundary.
Frequently asked questions
Can a CSV import be cancelled after it starts?
It should not be treated as cancellable. Shopify’s import guidance says that an import cannot be cancelled once it starts, so export, rehearse, approve, and prepare recovery material before upload. If a problem appears after start, record the processed scope, stop later batches, read the result, and repair the smallest approved range. Do not promise a platform undo or a complete import-history restore.
Why must the handle be checked when updating an existing product?
The handle participates in product identity and URL context, while an equal title does not prove equal identity. Resolve a verified handle, SKU, or resource ID before updating, and treat zero, one, and multiple matches as different outcomes. Approve a handle change separately; changing it first can remove the original lookup path to the old value.
How should rows and images be arranged for a product with variants?
Use the current Shopify CSV template’s product-first-row, variant-row, and image-row relationships, then verify them in a small sample. Each option combination and SKU should be unambiguous, and each image row should retain its product or variant relationship and expected order. Do not infer inheritance only from blank cells; use the template, preview, and read-back result together.
Is productSet the same as a native two-way Shopify sync?
No. productSet is an Admin GraphQL product create/update capability with documented list-field, omission, synchronous/asynchronous, and variant limits. It does not supply an external scheduler, cursor, conflict owner, replay policy, or two-way source of truth. Recurring synchronization is a separate 9917 operating problem.
How do you return to the last verifiable state after an import failure?
Stop expansion and retain the export, input checksum, preview, result, and failed rows. Determine whether the failure is at product, variant, media, or field scope, then create the smallest reverse patch containing approved old values. Read back and compare after the patch. If old values, current values, or platform state are incomplete, pause for human review. This is an evidence-based procedure, not an automatic Shopify transaction rollback.
Official source register
- Shopify product import
- Shopify CSV fields and format
- Shopify common import issues
- Shopify Admin GraphQL Product object
- Shopify productCreate
- Shopify productUpdate
- Shopify productSet
- Shopify productVariantsBulkUpdate
- Shopify GraphQL bulk operations
- Shopify API limits
- Shopify webhooks
- Shopify inventory transfers