Migrating to CLAJAMA is ridiculously easy
Upload your Shopify CSV or WooCommerce XML. We normalize everything β variants, images, collections, customers. No mapping. No scripting. No data loss.
The old way vs. CLAJAMA
Shopify / WooCommerce / Custom CSV
-
Denormalized CSV exports
Each variant is a separate row. Good luck reconstructing products programmatically.
-
CDN-locked images
Your product images are on Shopify's CDN with expiring URLs. Migration breaks them.
-
Proprietary API formats
Each platform has a different REST API, auth scheme, and rate limiting.
-
No validation before import
Upload β hope it works. If it doesn't, you get a generic error with no way to fix it.
-
Lock-in to their ecosystem
Once you're on their platform, moving your data out is painful by design.
CLAJAMA
-
Normalized schema
Products with multiple variants collapse into one clean record. Slug, title, variants, images β all structured.
-
Auto image re-hosting
We download Shopify CDN images to your local filesystem. No broken images after migration.
-
Adapter pattern β one interface
Shopify, WooCommerce, custom CSV β all return the same Product/Variant schema. Swap sources in one line.
-
Validation with error reports
Dry-run first. See exactly which products have issues (missing title, negative prices, no images). Fix, then import.
-
Open source β zero lock-in
Your data is in a portable SQLite store. No proprietary formats. You own it.
How the pipeline works
The cleanest migration system you'll ever use. Three stages, zero surprises.
Extract
Upload your Shopify CSV. Our adapter handles the denormalized format β variant rows, option axes, image URLs, customer data. All in one pass.
# One adapter per source. Same output format.
adapter = ShopifyAdapter()
result = adapter.extract("products_export.csv")
Validate
Every product is checked: required fields, price integrity, SKU uniqueness, image presence. Errors block, warnings advise. Nothing slips through.
# Dry-run first to preview issues result = Validator().validate(result) # result.errors β what's broken # result.warnings β what's advisory # result.skipped β how many were rejected
Store
Products land in a normalized SQLite store. The EcommercePlugin reads from this store β it never touches raw Shopify data. Swapping sources is a pipeline change, not a plugin change.
# Full import python -m cli.migrate products.csv --from shopify # Delta β only new products python -m cli.migrate new_export.csv --from shopify --delta # Adding WooCommerce to same store python -m cli.migrate woo_export.xml --from woocommerce
Feature comparison
| Shopify | WooCommerce | Custom CSV | CLAJAMA | |
|---|---|---|---|---|
| Export format | Denormalized CSV | WXR XML | REST API JSON | Single normalized schema |
| Image handling | CDN URLs | Attachment IDs | CDN URLs | Auto re-host to local |
| Multi-variant products | 1 row per variant | Variable products | Variant objects | Single record, variants array |
| Import validation | None | None | None | Dry-run + error reports |
| Delta imports | Full re-export only | Plugin required | API-based | Built-in delta tracking |
| Multi-source merge | β | β | β | β Import multiple sources |
| Data portability | Locked in | MySQL dump only | Locked in | Open SQLite + JSON |
| Cost to migrate out | $$$ (apps + dev time) | $$ (custom scripts) | $$$ (API rate limits) | $0 (open source) |
Add a new source in ~30 minutes
The adapter pattern makes it trivial. Write one class, register one line:
# migration/adapters/custom_csv.py class CustomCSVAdapter(AdapterBase): source_name = "custom" def extract(self, source, **kwargs) -> ImportResult: # Map any CSV columns to our schema products = self._parse_csv(source) # Only work is column mapping normalized = [self._to_product(row) for row in products] return ImportResult(products=normalized, ...) # cli/migrate.py β one line to register ADAPTERS["custom"] = CustomCSVAdapter
The ImportResult schema never changes. The Store never changes. The EcommercePlugin never changes. All migration work lives in the adapter.
Ready to migrate?
Upload your export, see what we catch, and get a clean store in minutes.