Importing into EcomSolo
Imports let you bulk-create and bulk-update data in your Shopify store from a spreadsheet — or straight from another store you've connected. Upload a file, tell EcomSolo which column means what, preview the result, and run.
EcomSolo imports follow the familiar spreadsheet workflow, so if you've used Shopify's own CSV exports or other bulk import/export tools before, your existing files will map automatically.
You don't have to import one entity at a time, either: upload a single Excel workbook whose sheet names are entities (Products, Customers, Blog Posts, Redirects, …) and EcomSolo imports every sheet in one run, in dependency order — see Import a whole store from one workbook.
How an import works
Every import goes through the same four steps, followed by a live run screen:
- Choose what to import — pick the entity (Products, Inventory, Customers, Blogs, Blog posts, Collections, Companies, Discounts, Files, Gift cards, Locations, Menus, Metafield definitions, Metafields, Metaobjects, Orders, Pages, Shop, or URL redirects) and the operation.
- Choose your source — upload a file (CSV, Excel, or JSON), fetch one from any URL (including Google Sheets), paste raw JSON, pull from another store, or re-use a previous import.
- Map your columns — confirm which spreadsheet column feeds which field. Auto-detect does most of this for you.
- Review and run — see a dry-run preview of what will happen, then run it now or put it on a schedule.
The step rail on the left shows your progress. You can click back to any completed step to change something before you run.
Step 1 — Choose what to import
Pick the entity type and the operation. Every row is matched against your store by the entity's natural key (a product's handle, a redirect's path, an order's name, a customer's email, …) and the operation decides what happens:
| Operation | Row matches an existing record | Row doesn't match |
|---|---|---|
| Create only | ❌ fails ("already exists — use Update or Upsert") | ✅ created |
| Update only | ✅ updated | ❌ fails ("cannot update: no existing …") |
| Create + Update (upsert) | ✅ updated | ✅ created |
| Merge (partial update) | ✅ updated — but only the columns present in your file are touched; everything else keeps its current value | ❌ fails — Merge never creates |
| Delete | removes the record (permission-gated, destructive) | skipped |
Upsert is the recommended default — it makes imports safe to re-run: running the same file twice updates in place and never creates duplicates. The dry run on the Review step predicts the same outcomes per row before anything runs.
A few entities have deliberate exceptions:
- Products reject Merge — Shopify's
productSettreats variants and options as the complete desired state, so a partial file could delete variants. Use Upsert with full rows, or Update. - Gift cards are create-only — every row issues a NEW card (codes are masked after issue, so there's nothing to re-match). Update/Merge are rejected.
- Inventory rows set quantities on existing items — Create is rejected (nothing is ever created); Upsert/Update/Merge all behave the same.
- Shop is update-only by nature (only shop metafields are writable).
Delete is available for every entity with a Shopify delete API (products, customers, orders, draft orders, collections, pages, blogs, blog posts, files, menus, URL redirects, companies, locations, metafields, metaobjects, and discounts). It is gated behind the delete via import permission and is irreversible: a delete file needs only the entity's identity column(s), the dry run shows a red "Will delete N" count before anything is written, rows that match nothing are skipped (so re-runs are safe), and your dashboards drop the deleted records within seconds of the run. Shop, Gift cards, and Inventory have no delete API — Delete runs for them are refused up front with a clear error (gift cards can only be deactivated).
Step 2 — Choose your source
You have several source tabs:
| Source | What it is |
|---|---|
| Upload file | Drag and drop a CSV, Excel (.xlsx), or JSON file. |
| From URL | Any direct link to a CSV / Excel / JSON file — or a Google Sheets link. Re-fetched on every run. |
| From another store | Import directly from another connected store. Requires a paid plan on the destination store. |
| Paste JSON | Paste a JSON array of objects straight into the wizard. |
| Re-use previous | Re-run any earlier import — same file, same column mapping, no re-upload. |
Upload a CSV, Excel, or JSON file
- CSV files can use quotes, commas inside quoted fields, and multi-line cells — standard spreadsheet exports just work.
- Excel files must be
.xlsx(the older binary.xlsformat is not supported). Formulas are imported as their computed values. A single-entity import reads the first worksheet; if two or more worksheets have recognized entity names, the wizard offers to import the whole workbook in one run. - JSON files follow the same shape as the Paste JSON tab below.
- Files up to 100 MB and 50,000 rows are supported.
From URL
Paste any direct http(s) link to a CSV, Excel (.xlsx), or JSON file — a
supplier's export URL, a Dropbox/S3 direct-download link, another app's feed.
The file type is detected from the URL's extension or the server's content
type, and everything downstream (mapping, dry run, report) behaves exactly
like an uploaded file.
- The URL is fetched fresh on every run — nothing is stored except the link itself. Put the import on a schedule and a supplier feed at a stable URL becomes a recurring sync: the supplier updates the file, your next scheduled run imports the changes. That's the whole recipe.
- Password-protected feeds (HTTP basic-auth) work by putting the
credentials in the URL:
https://user:password@example.com/feed.csv. - Files up to 100 MB, same as uploads. Links must be direct — a page that merely links to the file won't parse.
Google Sheets links get special treatment: paste the sheet's share link into the same box and EcomSolo reads it via the Sheets integration.
- The sheet must be shared as "Anyone with the link can view." No Google sign-in is needed — but if the sheet is restricted, the import can't read it and you'll see a clear error asking you to update the sharing setting.
- The tab referenced in your link is the tab that gets imported, so you can link to a specific tab of a multi-tab workbook.
Paste JSON
Paste (or upload) a top-level JSON array of objects — the natural shape of most API responses and app exports:
[
{ "Handle": "blue-hat", "Title": "Blue Hat", "Tags": ["summer", "sale"] },
{ "Handle": "red-scarf", "Title": "Red Scarf" }
]
- Keys become columns, mapped in Step 3 exactly like CSV headers.
- Nested objects flatten to dot-paths —
{"Seo": {"Title": "…"}}becomes theSeo.Titlecolumn. - One array of objects per record becomes multiple rows — an order like
{"Name": "#1001", "LineItems": [{…}, {…}]}expands into one row per line item with the order fields repeated, which is exactly how the multi-row entities (Orders, Draft Orders, Menus, Companies) expect their rows. Two or more object-arrays on the same record is ambiguous and is rejected with a clear error. - Arrays of plain values join with commas —
"Tags": ["a", "b"]imports like the CSV cella, b.
The pasted JSON is stored like an uploaded file, so re-running, resuming, and scheduling all work the same as any other import.
From another store
If you have more than one store connected, you can import directly from one store into another — no export file, no re-upload, and no extra Shopify API usage on the source store. This works for Products, Customers, and Inventory.
Paid feature. Importing from another store requires a paid plan on the destination store (the store you're importing into). Every other source — file upload, URL, Google Sheets, and Paste JSON — is available on all plans, including free. If the destination store is on the free plan, the tab shows an upgrade prompt; upgrade that store's plan to unlock store-to-store copies.
- Add an optional source filter and a search to import just a slice; the tab shows a live "N match" count that is exactly what the import will process.
- Products come across with full fidelity: every variant, option names and values, all images, and the "Track quantity" setting — so tracked products stay tracked and can receive an inventory import afterwards. Image files are copied to the destination automatically.
- Customers bring their profile, all addresses, tags, and writable marketing consent, matched by email. See Importing Customers.
- Inventory copies each SKU's total on-hand into the target store's location, matched by SKU. See Importing Inventory.
- Column mapping is pre-filled for you — the source already uses EcomSolo's field names, so the mapping step is usually just a confirmation click.
Put a store-to-store import on a schedule and you have a recurring one-way sync: the destination store is updated from the source on every scheduled run, filter included.
Re-use a previous import
The fastest way to run an import you've run before. The tab lists your earlier imports of the same entity — pick one and EcomSolo clones its source and its saved column mapping into a new import, landing you on the mapping step with everything pre-filled, one click from Review.
- Works for every source kind: an uploaded file, a URL (including Sheets), pasted JSON, and store-to-store (the source filter comes along too).
- Nothing is re-uploaded — the original file is re-read as-is. URL, Sheets, and store-to-store sources are re-read live, so they pick up changes since the original run.
- The new import uses your current wizard choices for the operation and target store — so "re-run last week's products file against my other store" is a two-click flow.
- The list shows each run's outcome (created / updated / failed counts) so you can tell runs apart before re-using one.
Step 3 — Map your columns
EcomSolo reads your file's headers and auto-matches them to the right fields. Headers from Shopify's CSV exports and other common import/export tools are recognized out of the box — Handle, Title, Body (HTML), Variant SKU, Variant Price, Option1 Value, Image Src, SEO Title, and so on all map automatically. Anything the auto-detect isn't sure about, it suggests by closest name match.
You stay in control:
- Override any suggested mapping with a different field.
- Mark columns you don't want imported as ignored.
- Save the mapping as a template so future imports of the same file layout are one click.
Step 4 — Review and run (dry run)
Before anything touches your store, EcomSolo runs a dry run — a full preview that never writes to Shopify. You'll see:
- Will create / Will update / Will skip counts.
- Up to 50 row-level issues, with the row number and the reason, so you can fix your file before running.
A dry run is a prediction, not a guarantee — a few things (like store-wide SKU uniqueness or whether an image URL is reachable) can only be checked by Shopify during the real run. Rows that fail then are captured in the import report.
When you're happy, either:
- Run now — the import starts immediately, or
- Run on a schedule — attach a recurring schedule instead of running once.
The Run screen
Once a run starts, the wizard's final rail entry shows live progress: rows processed and created / updated / failed counts as the import works through your file. You can also leave the page — the import keeps running in the background, appears in your Imports dashboard, and sends you an in-app notification when it finishes.
Scheduled imports
Any import can be saved as a recurring schedule instead of a one-time run. On each scheduled tick, EcomSolo re-reads the source and applies it with your saved column mapping:
- File uploads re-run against the uploaded file.
- Google Sheets re-fetch the live sheet — edit the sheet, and the next run imports the changes.
- From URL re-fetches the link on every run — a supplier feed at a stable URL becomes a recurring sync.
- From another store re-queries the source store (with your source filter), making it a recurring one-way product sync between stores. If the destination store's paid plan lapses, the scheduled run fails with a clear "requires a paid plan" message rather than silently copying.
Schedules appear in the Imports area alongside your run history, and each scheduled run produces its own history entry and report.
The import report
Every run produces a downloadable CSV report — one line per row of your source file, successes included:
| Column | Meaning |
|---|---|
Row | The data row number in your file (row 1 is the first row under the header). |
Status | created, updated, skipped, or failed. |
Shopify GID | The Shopify ID of the record that was created or updated. |
Errors | Why a row failed (multiple reasons separated by a pipe). |
Source: … | Every original column from your file, reproduced exactly. |
Because your original columns are included, the fastest fix loop is: filter the report to failed, correct those rows, and re-upload just them — upsert means the already-successful rows are safe to include too.
Download the report from the import's row menu in the Imports dashboard ("Download error report"). It's available even for fully successful runs.
After the run: your dashboards refresh right away
As soon as a run completes, EcomSolo re-fetches the imported records from Shopify and refreshes its own indexes — so they show up on the matching dashboard within seconds, not on the next sync cycle. This also keeps re-runs accurate: importing the same file again a minute later correctly updates instead of trying to re-create.
A products import that also set stock (the inventory columns on the Products sheet) refreshes the Inventory dashboard too — the touched items show their new quantities right away, including items belonging to products the run just created.
FAQ
Can I undo an import? No — imports write to your Shopify store, so there's no automatic rollback. Use the dry run to verify before committing, and start with a small test file for a new layout.
What happens if I run the same file twice? With the default Upsert operation, nothing bad: existing records are updated in place and no duplicates are created.
My upload has errors on some rows. Did the rest import? Yes. Row-level problems never stop the run — good rows are applied, failing rows are recorded in the report, and the run finishes as "Partially completed."
What if my internet drops or I close the tab mid-run? The run continues on our servers. Progress is checkpointed as it goes, so even a server interruption resumes where it left off rather than starting over.
Does an import count against my Shopify API limits? Imports do call Shopify's API, but EcomSolo automatically paces requests against Shopify's rate budget and retries throttled calls, so an import won't starve your store's other apps.
Which entities can I import? All of them: Products, Inventory, Customers, Collections, Orders, Draft orders, Discounts, Gift cards, Companies (B2B), Locations, Metafield definitions, Metafields, Metaobjects, Pages, Blogs, Blog posts, Files, Menus, URL redirects, and Shop settings. Each has its own guide in this section, and you can import several at once with a multi-entity workbook.