The Import and Export tools let you move a whole site between accounts, or bulk-load your catalogue without typing everything by hand.
This is the last guide in the Help Center, but you may need it first: if you're migrating from another platform, start here instead of entering your catalogue by hand.
What it is
- Export downloads your content as a file.
- Import loads such a file into the current account.
There are two kinds: a whole site (a bundle) and products (a spreadsheet).
Whole site
- Export full site creates a JSON bundle with your content and settings - without secrets (no tokens or payment instructions, no customer orders).
- Import full site uploads the bundle and shows a per-section preview - what will be created, updated and deleted - and applies the changes only after you confirm. Each section expands to the list of rows that change. Images are re-hosted automatically - the photos inside blog posts and the logo included, even an SVG logo - and optimised the same way as a direct upload (the shop generates smaller WebP copies for each screen size), and imported redirects go live straight away.
- Catalogue codes. A product the import creates does not take a code another product or variant in your shop already carries, nor one an earlier product of the bundle already took - the first one keeps it. The product is created without that code, and the preview names the holder under it. A product without variants counts by its own code and each variant by its own; the code of a product with variants (its parent code) does not count. "Replace" deletes the catalogue first, so there only the bundle's own products are compared. After the import, the Done step lists these products in a "Refused SKUs" card - each with a field for a free code and a Save button, checked exactly like the product editor.
- An unfinished import is offered to Continue or Discard when you reopen Full site (and from the import history). Continuing returns to where you stopped: a run not yet confirmed returns to its preview, a started one keeps writing, and a file that was uploaded but never reached the preview reopens at the Sections & mode step, without uploading it again.
Exactly what's in the bundle
Your shop's brand name, theme, navigation, services, products (including their catalogue codes, their shipping weight and dimensions - down to each variant - and their titles, descriptions and delivery lines in every language), blog, FAQ, promotions and codes, product bundles (percentage-discount ones included), email templates and branding, your SEO settings (per-page, per-category and per-product titles, descriptions and social-share images), your 301 redirects (old URL → new URL), legal settings (legal entity, company number/ЕИК, edited legal text), your languages and customised translations, the home-page arrangement (handpicked-product blocks and the images in banners, galleries and showcases included), the announcement bar, the About section (with its photos), testimonials, and the AI assistant's name and greeting.
The order of products inside each category travels too - a product you placed by hand keeps that place in the new shop, separately for every category it sits in. Categories bring their category image, their menu badges, their own description-section text, their "SEO & sharing" settings (SEO title, meta description, social share image) and their Old URL (for redirects) with them.
Variants keep their options. Each variant's size, colour and other options are linked to the new shop's attributes, and personalised products keep their per-colour mockups. An option that matches nothing in the new shop is listed under the warnings after the import - fix it in the product editor, or that variant can't be picked on the storefront.
Quantity pricing on each product - on or off, with its rows - travels too. In a shop whose plan does not include it (Solo) the tables are kept, but the shop sells at the single-unit price until its plan does.
Your shop's look travels too: the header layout and logo size, the call button and the map beside the address, the footer (with its logo), the «Delivery & payment» and «Returns & exchanges» pages, the checkout page notice, the newsletter sign-up and its pop-up (with its images), the cookie banner, the menu width and how search shows, the carousel's frame and dots, the product card settings (the favourites heart, ratings, quantity pricing, sold-out products) and the product page settings (related products, the sold and viewed counts, Fast order), and the low-stock level. A file exported before 2 October 2026 carries none of these - the new shop then keeps its own.
Your opening hours travel as a schedule: the days and hours from Settings › General › Opening hours and whether the site shows them. The import writes them over the new shop's business hours; each team member's own hours stay as they are. A file exported before 20 October 2026 carries the hours as text: the sign-up text (such as "Mon-Fri 09:00-18:00") becomes the schedule and shows on the site, and any other text does not carry over - the preview says so, so you can enter it by hand.
Not carried are the settings tied to a particular shop's contracts and domain: delivery (free delivery over an amount, and the couriers with their accounts), payments, your plan and the features it includes, search-console/IndexNow verification and analytics IDs. Set them by hand in the new shop after the import.
Turn off Copy images into this account to keep each item's original image URLs instead - useful for a dev/staging copy that should point at the live site's images.
Large catalogues (thousands of products) are supported: the file uploads in one go with no size limit, and images are copied in groups with a visible progress counter ("Copying images… 120/1404").
Only the images the import writes are copied. "Images to upload" in the preview and the counter during the import count only the images of the sections you pick - import just "Home page & identity" and "Blog posts" and none of the catalogue's photos are copied. With "Add missing", only the images of the rows that will be created are copied: an existing row is left untouched, its images with it. Category images and the catalogue's banner come with every products import.
An image already copied is not downloaded again. An image from the same link that an earlier import already copied into the shop is reused as it is - no download, no re-optimising - and counted apart: "… · 3461 already copied" during the import and "…, 3461 already copied earlier" in the result. That is why re-importing the same file goes much faster. An image replaced on the old shop at the same link keeps its earlier copy - replace it by hand in the BackOffice.
Just the home page, without the catalogue. Import "Home page & identity", "Navigation menu" or "Hero carousel slides" without "Products & categories", and their blocks (handpicked products, categories, menu links, banner and slide links) are linked to the products and categories the shop already has - by the same address (slug). If some are not in the shop, the preview says so on the section - the sections pointing at them stay empty until you import "Products & categories" too (for example in "Add missing" mode).
"Replace" won't work on a site with orders
You can't Replace the products of a site that already has orders - existing products can't be deleted. Use "Add missing" or "Append" for products, or import into a fresh site.
Typical use: set up a demo account, export it, and import into your live account.
Products
- Export products downloads your whole catalogue as CSV/Excel, with column headers in your BackOffice language. The columns cover the whole product, grouped like the editor: Basics (title, address, short description, delivery line, images), Selling (SKU, price, compare-at price, cost, stock, barcode, weight and dimensions - length/width/height in cm), Organization (category, additional categories, badges, Meta advertising, hidden, archived, Art. 57 exception), Related (related products and variant group) and SEO (SEO title and description, OG image, focus keyword and additional keywords, Meta ad title and description, Google category). Categories are written as their full path ("Models > BMW E60 E61"), so a re-upload recognises them even when two categories share a name. Availability and visibility export as Stock, Hidden and Archived - never as a status word, so the file can never carry two contradicting inventory signals. Hidden is the product's own switch (shoppers do not see it, but it stays in the active list - see Products), and Archived is the archive. A file without an "Archived" column (for example one downloaded before it existed) never un-archives a product: there "Hidden" only hides or shows. Variants are included: a product with variants exports as its product row followed by one row per variant (see "Attributes and variants" below). The Barcode column is blank on the product row: a barcode lives on a variant and is written on the variant row. The spreadsheet holds the products themselves - it does not carry your category settings (each category's layout, campaign and sections), the order of products inside each category, product bundles or personalisation; the full-site export keeps those.
- Import products loads products from CSV/Excel - you map the columns, preview a dry run, then confirm.
- .xlsx files are read not only from Excel and Google Sheets, but also from most programs and scripts that build spreadsheets themselves. This applies to every import (products, customers, subscribers, orders). If a file cannot be opened (for example it is damaged, password-protected, or written by a program that saves the format in an unusual way), you see a message to open it in Excel or Google Sheets, save it again as .xlsx and upload that copy.
The «Указания» (instructions) sheet and the Excel conveniences
When you export to Excel (.xlsx), the file has two sheets: «Продукти» (the table itself) and «Указания» - an automatically generated legend with one row per column: what the cell accepts, an example, and your own valid values (your categories as full paths, your badges, each attribute's values), followed by the rules (a blank cell is left untouched; [clear]; | between images and a comma between names; the variant rows and the parent code; unknown names are flagged; nothing is ever deleted). The sheet is built from the same columns as «Продукти», so it can never describe a column that does not exist.
The table itself also comes with small Excel conveniences: a frozen (pinned) header row, sensible column widths, numeric cells for price and stock, and dropdowns on Category, Badges, Hidden, Archived and every Attribute: column (the values come from a hidden helper sheet). These are only a help - a plain CSV without them imports in exactly the same way; the dropdowns do not constrain (you can type a full path by hand, or several comma-separated badges). The CSV file carries the products sheet only.
Create and update from one spreadsheet
The same file now creates the new rows and updates the existing ones - the monthly loop: download the export, edit in Excel, upload it back. A cell you did not touch is not a change: the preview shows only what you edited. Numbers read back exactly (a 0.458 kg weight stays 0.458), Cyrillic addresses are not rewritten in Latin letters, attribute values and keywords with a comma inside stay whole, and related products without a catalogue number (which the export cannot write) are kept.
- One identity column. On the mapping step you nominate ONE column that says which product each row is: catalogue number, address (slug), old address, or title. Only that column matches - no fallback rules, so every row can say why it matched. A code that exists both as a product and as a variant points at the product; a code held only by a variant updates that variant's own numbers (price, was-price, cost, stock, barcode, weight, image) and never touches the parent - a per-size restock sheet just works. Under the picker the step says what will happen to the file: how many product rows carry a value in that column, how many rows without one will be created as new, and how many will be blocked because they carry another product's title (pick a column where they have a value then - the address, for example). Variant rows (with "Parent code" filled in) are counted apart: they never create a new product and find their product through the same column - so re-uploading your own export never promises a single new product.
- A row with a blank identity cell is created as a new product - unless its category already holds a product with the same title: then the row is blocked so no duplicate appears, and we ask you to add a code. If the same title exists in a different category, a code-less row is blocked too (we name that category - add a code to create it as a separate product, or use the existing product's code to update it); a row that carries its own new code matching nothing is created normally, but with a warning that the name already appears in that other category - because a distinct new code already says "new product". A title can PREVENT a duplicate; it never authorises an update.
- Ambiguity is an error, never a guess. A code matching two records (or two file rows pointing at one record, or a repeated code on new rows) lands in "Needs review" naming both sides, and neither is written.
- Only mapped columns take part, and a blank cell changes nothing. A stock-only sheet touches stock only. Stock is an absolute number; an explicit number always beats a status word.
- Clearing a value: write
[изчисти]in that one cell ([clear]works too, any case). Only that text empties a field - a blank cell always means "leave it". In a list column (images, badges, additional categories) it empties the whole list; in Stock it means "untracked"; in Hidden, Archived and Meta advertising it means nothing and only warns. Where emptiness is not a state - the code you match by, the title, the price, the address and the category - the row goes to "Needs review" naming the cell and nothing on it is written. The preview shows a clear as "(empty)". - Values are mapped too. A status column (available/out of stock/…) translates to a state - stock, hidden, archived - through a table you fill in once; you can also attach a badge of your own, which the import both adds AND removes. "Available" never lowers a counted stock: a product with 24 units keeps its 24, the word acts only when the stock is 0 or untracked.
- Categories are assigned by the sheet and created in the editor. The category cell (and each additional category) must name an existing category - by the full path from the export ("Parent > Child") or by its name when that name is unique. The values step lists every distinct value with its row count and lets you match it to a category; a value left without an answer sends its rows to "Needs review" and nothing on them is written. A spreadsheet never creates a category - a category is a layout, a banner, SEO and a place in the menu, not just a name.
- Images are recognised by their source address. Re-uploading the same vendor file moves not a single byte - already-hosted ones are skipped. A non-blank images cell makes the gallery exactly the listed URLs in that order; a blank cell leaves it alone; a dead URL is recorded as a warning and never blocks its product. An update never downgrades a gallery: if any of the new images cannot be fetched, the product keeps its current pictures and the row gets a warning - its other fields are still written. A slug that already belongs to another product likewise stays unchanged with a warning.
- The "Re-host images to our storage" switch is on for every new file. Turn it off and images are written as external links (exactly as they are in the sheet) - the preview shows those very links. New products get them; an existing product whose images are stored in ZweiHost keeps them - an external link never replaces an uploaded picture, and the row gets a warning. The switch is not carried over from an earlier import.
- The preview is a report in four tabs - To create · To update · Unchanged · Needs review - each searchable and filterable, and every row expands to a full "now / after the import" comparison. Nothing is written until you confirm; two switches ("Only new" / "Only updates") restrict the run.
- Lowered stock is recorded as a write-off. When the file lowers the stock of products or variants, a card «The stock of … goes down» sits above the preview tabs, listing every decrease (before → after, how many units), and asks one reason for the whole file - «Correction» preselected, an optional note (required for «Other») and a date (today or earlier). For a loss reason the card says what the units are worth at their current cost. Each decrease is recorded in Products › Inventory › Write-offs with that reason and is undone there one by one; increases are not recorded. For a product that sells by catalogue the file changes its own stock (the Base values row of its price table) - and a decrease there is recorded too. With «Only new» on, nothing is updated and nothing is written off. When the import finishes, the Done card says how many write-offs were recorded and links to them.
- The run goes in groups, in two phases: the images first (40 per request - "Group N of M") - only for the rows the switches will write - then the database writes (25 per request). A closed tab loses nothing - an unfinished import is offered for continuation, every row is re-checked, and already-written ones pass as "unchanged" with no duplicates. A second tab cannot start a running import over - it can only continue it.
- The import history (the last 20 runs) keeps the exact counts, the warnings and the original file for re-download; the column and value mapping pre-loads from the last run over the same columns (the images switch does not - it always starts on).
- Bulk update is available from the Pro plan up. On Solo the whole new preview works, but update rows are locked and the run creates only the new products.
Warnings after the import, and retrying images
After an import (on the Done step and from the import history) the warnings are no longer one long list - they are grouped by type and ordered by importance: what needs a look is at the top, and notes that need no action are below. The row badge shows the count to review ("N to review"), not the raw total.
- Failed images can be retried from here. If some images didn't download from their source in time during the import (usually a temporary problem at the image host), the "Images that didn't upload" card has a "Retry the upload" button. It re-fetches only the still-missing images - with a longer timeout and a gentler pace - puts them on your CDN and updates the affected products. Progress shows in place; if some images still fail, a button lets you retry just the remaining ones.
- An image reverted to its source keeps showing on the storefront via the original link - the retry simply moves it onto your CDN (optimised and independent of the other site).
- You can download a CSV of the affected rows for each warning category, to check the products one by one.
SKU
Both the import and the export carry an SKU column - your own catalogue code for each product, the one you are used to on your old platform. It is recognised automatically from headers like SKU, Артикулен номер or Каталожен номер; if yours is named differently, map the column by hand on the mapping step.
- On a product row the code is saved on the product; on a variant row (one with a "Parent code") it is that variant's own code. A row whose code matches an existing variant's code updates that variant's own numbers, and a variant row with a new axis combination creates the variant - see "Attributes and variants" below.
- A blank cell means "no code" and erases nothing. A code-less row is created as a new product (or blocked by title - see above); a file without this column cannot wipe the codes you already hold.
- Duplicate codes are errors. Two rows carrying one code, or a code matching two records in the shop, land in "Needs review" naming both sides and are not written - otherwise one would silently overwrite the other.
- A code that is already taken is not written. A row that sets a code another product or variant in your shop already carries - or one an earlier row of the file already writes - is written without that code: a new product or variant gets no code, an updated one keeps its old code. The preview names the holder. When you match by SKU, two rows with the same code are still an error. After the import, the "Refused SKUs" card - first among the warnings on the Done step and in the Import history - lists these products and variants with a field for a free code and a Save button. The check is the product editor's: a taken code is refused, naming the product that carries it; a saved row stays in the list with a green tick.
- The export includes the same column, so download → edit in Excel → re-upload keeps your codes intact.
Short description
The "Short description" column (formerly just "Description") is the product's plain lead text - the one under the title on cards, and the source for your Google description. The long, formatted body is a separate product section, not this column.
Shop platforms store the description as HTML - in WooCommerce the column is Description (or post_content), in Shopify it is Body (HTML). The import recognises this on its own and brings in the readable text only, because "Short description" is shown as plain text.
- If the cell contains HTML the row imports normally, and the dry run notes "Description was HTML - imported as plain text".
- The first substantive paragraph is taken, up to 240 characters. A long multi-section description is not lost - it simply is not what belongs under the product title; the rest goes in the product's "Sections" tab.
- Leftovers from the old theme are cleared too. If the description contained an embedded product grid, a banner or a block of styles (the kind WordPress bakes into the text itself), none of it comes across - otherwise your new shop would display the old site's product names, ratings and prices in лв.
- Plain text is imported exactly as written.
Delivery line
The "Delivery line" column is the sentence under the price that a product shows instead of the shop's line, e.g. "Made to order - ships within 4-6 weeks.". A blank cell changes nothing, and [clear] removes it so the product shows the shop's line again. The other languages go in twins such as Delivery line [en]. What the shop shows when the line is empty is in Products.
Price and "was" price
Platforms describe the price pair in one of two ways. Shopify and CloudCart give now + was ("Variant Price" / "Variant Compare At Price"; "Цена" / "Стара цена") and are read directly. WooCommerce does the opposite: "Regular price" is the undiscounted one and "Sale price" is what the customer actually pays whenever it is filled.
- If your file has a sale column, map it to Sale price. The customer then sees that price, with the regular one struck through beside it.
- If the sale price is blank on a row, that product imports at its regular price with no discount.
- If the sale price is not below the regular one, the product still imports at it but with no struck-through price - a discount of zero is not worth showing - and the row is flagged in the dry run.
- The column is import-only. It is not in the export, where the price and the "was" price are already separate columns.
If the file's new prices make an active bundle no cheaper than its products bought separately, the Import complete card names it, with a button to it. The bundle stays active - see Bundles.
Quantity pricing
On the Pro plan and above the sheet has a Quantity pricing column on the product row (variant rows stay empty): the rows from row 2 on, separated by | - 6+: 4,00 | 21+: 3,50 for a price per piece or 6+: 20% | 21+: 30% for a percentage off; row 1 is the Price column. A blank cell switches quantity pricing off for that product, and a file without the column leaves it alone. A cell that cannot be read sends the row to Needs review. In a shop whose plan does not include quantity pricing (Solo) the column is skipped with its reason in the Map columns step and cannot be mapped to another field, such as Stock. The full rules are in Quantity pricing and on the «Указания» sheet.
Dimensions, returns, SEO and links
Beyond the basics, the sheet also carries:
- Shipping dimensions - "Length (cm)", "Width (cm)", "Height (cm)" next to "Weight (kg)". They feed volumetric weight in the courier quote.
- "Art. 57 exception" - the point of Art. 57 of the Consumer Protection Act under which the product may be an exception to the right of withdrawal:
т. 3,т. 4,т. 5,т. 6,т. 9orт. 10(pt. 4works too; blank ornone- no exception). The old "Non-returnable" column is still recognised:yesmarks an exception with no ground given (and never replaces a ground the product already has),noremoves it. - SEO columns - "SEO title", "SEO description" and "OG image" (the page's meta tags); "Focus keyword" and "Additional keywords" (the editor's SEO coach); "Meta title" and "Meta description" (the separate ad-catalogue copy, NOT the meta tags); and "Google category (id)" (the numeric id from Google's taxonomy).
- "Related products" - the other products that "go well with" this one, listed by catalogue number, comma-separated and in the order they should show. A product with no catalogue number cannot be referenced (so its own "SKU" cell is blank - that makes it visible). The cell is authoritative: it replaces the whole list;
[clear]empties it; an unknown code is skipped with a warning, and a cell of only-unknown codes does not wipe the existing links. - "Variant group" - the name of the variant group (set on the product's "Variant products" card). Rows sharing the same name form one group. The import never moves an already-grouped product to another group (that stays an editor action - a row with a different name only warns); a blank cell changes nothing, and
[clear]removes the product from its group.
Sections and languages
Beyond the fixed columns, the export adds two column groups built from your own sections and languages - they are recognised automatically on re-upload, with no mapping step:
Секция: <title>(Section: <title>) - one column per enabled per-product section (the ones whose content is written on each product, not the shared ones). The cell accepts HTML and is stored as-is (unlike "Short description", which keeps only the lead text) - this is where a product's long, formatted body lives. A section is matched by its title; if you rename a section, the old title in the file is simply skipped with a warning (nothing else on the row is affected), and if two sections share the same title that column is refused and we ask you to rename one.<Column> [code]- a language twin of every translatable column: "Title", "Short description", "Delivery line" and eachСекция:column, one twin per active non-default language (e.g.Title [en]). The default language stays in the column with no suffix. A twin for an inactive language is skipped with a warning - the file never creates or activates a language.
On the "Map columns" step these columns - and the Атрибут: columns below - map themselves: each one's dropdown shows where it goes (e.g. "Title · translation EN", "Section "Description" · EN", "Attribute "Model"") and it carries a "recognised automatically" label. Pick "- Not imported -" in the dropdown to leave the column out - for example when you only import new prices and want the translations and attributes untouched. A column that looks like one of them but cannot be recognised (an unknown or ambiguous section or attribute, an inactive language, a repeated column) stays at "- Not imported -" with the reason underneath - so you see the problem on that step, not only in the warnings after the import.
The "blank = leave it" rule holds here too: fill in only the language/section you are changing, and the rest stay untouched. [clear] in such a cell empties exactly that language of that section (or that one translation).
Attributes and variants
The export adds one Атрибут: <name> (Attribute: <name>) column per attribute (from your attributes tool). What the value means depends on the row:
- On a product row the values are specifications - comma-separated. They show in the product's "Characteristics" table and as catalogue filters.
- On a variant row the value is that variant's axis (e.g. "Size" = M). The combination of axes defines the variant.
Variant rows are marked by the "Parent code" column: fill it with the parent product's code (its value in the identity column - the export writes its catalogue number) and the row becomes a variant of that product, never a new product. Every product exports as a product row followed by its variant rows (each carries the parent code, its own catalogue number, price, stock, barcode and its value on each axis). On import a variant is matched by its own catalogue number, or - when it has none - by parent + axis combination; a new combination creates a new variant (values are added to the registry as needed - text values are created automatically, while a colour missing from the palette is skipped with a warning). A variant is never deleted or re-axed from a sheet - that stays an editor action. Two attributes with the same name make the column ambiguous and it is skipped until you merge them - the "Map columns" step says so on that column's row, with a "Merge attributes" link to the attributes tool; if one attribute is used both as an axis and as a specification of the same product, the axis wins.
Shopify (native)
If you upload a Shopify admin export (products_export.csv), ZweiHost recognises it on its own and takes you through a dedicated flow with no manual column mapping. Shopify writes one product across several rows (the first carries the product plus image #1, the rest carry only more images); every image is imported, in order, not just the first.
- Two languages. For each of your languages you pick where its text comes from: the standard columns
Title/Body (HTML), or a pair of custom metafields (e.g.titlebg+descriptionbg). The main language fills the product itself; the others become translations. The mapping is auto-guessed from the language code. - Sections. Your remaining
custommetafields (e.g.ingredients,formula,directions,size) become product description sections - bilingual when a pair exists (formula+formulabg). One toggle turns this off; you fine-tune the section titles afterwards under "Content → Sections". Shopify's ownshopify.*fields (gender, colour, age group…) are not turned into sections. - Also imported: SEO title and description, unit cost, weight, the Google product category, and status - drafts import hidden (in the active list, ready to finish and show) and archived products import archived.
- Re-uploading. Choose what happens to a product that already exists: "keep it" (the default, nothing is touched) or "update it in place" - matched by SKU, then by handle, keeping the same row so orders, bundles and links stay attached. If two products in your shop carry the same SKU (left from before SKUs became unique), the row updates the one whose handle or title matches; if neither tells which, the row is skipped - the preview and the result say why - instead of changing the wrong product.
- A code that is already taken is not written. A row that writes a code another product or variant in your shop already carries is imported without that code: a new product or variant gets none, one updated in place keeps its old code. The same goes when an earlier row of the file already writes the code (or another variant of the same product) - the first row keeps it. The preview names the holder. Only codes the row really writes count: a product keeping its own code, a row "keep it" skips, the variants a product keeps under "update it in place" and a parent code are never refused. After the import, the Import complete card lists these products and variants under "Refused SKUs", with a field for a free code and a Save button - checked exactly like the product editor. The Shopify import has no history, so the list lives only on that card.
- Lowered stock when updating in place. The preview first checks the stock of the products the file updates (the import waits while it checks). If the file lowers any of them, the preview shows the same card as the spreadsheet import - the list of decreases and one reason for the whole file - and each decrease is recorded in Products › Inventory › Write-offs. The variants of an existing product are left alone, so their stock does not change.
- Images on a re-upload. An image already stored in ZweiHost from the same link is not downloaded again - the stored copy is used. If, when updating in place, any image of a product cannot be downloaded (for example the old store has already removed it), the product keeps its current images and you get a warning - it is never left with a broken link where its picture was. For a new product, an image that cannot be downloaded stays as an external link so the product still has a picture.
- Variants. If a product has variants (Size, Colour…), they import as real variants: each axis becomes an attribute in your registry (as text - colours can be turned into swatches later), and every variant keeps its own price, stock, SKU and weight. On a re-upload the variants of a product you already have are kept (not overwritten), so orders are never disturbed.
- Characteristics. Shopify's standard
shopify.*fields (skin type, fragrance, product form, age group…) become product characteristics - shown in the "Characteristics" table on the product page. Each field is created as an attribute in your registry ("Products → Attributes"), and a multi-value cell ("adults; all-ages") splits into separate values. Attributes imported this way are not shown as filters by default - switch on "Show as a filter" only for the ones you want in the catalogue. Recognised names and values arrive already in Bulgarian (from a built-in dictionary of common Shopify fields); the rest (e.g. ingredient names, numeric values like "SPF 50") arrive in English - rename and translate them in the registry. One toggle turns the import off, and a field that is already a variant axis on the same product stays an axis (it is not duplicated as a characteristic). - Not carried across (yet): per-image alt text (images are stored as URLs only).
Customers
Import → Customers loads your customer list from CSV/Excel (e.g. an export from your old platform). It works like the product import: upload a file, map the columns (email, name, phone, address, city, postcode), preview a dry run, then confirm.
- Email is required - it's also the key we use to avoid duplicates. Every other field is optional.
- The import is idempotent: on a re-run, customers that already exist (matched by email) are skipped. Turn on "Update existing customers" to fill in name/phone/address from the file for people you already have.
- Duplicate emails within the file itself are detected - the first row wins.
- Phone numbers are saved in the international format (
+359888123456) - the same form your checkout uses - whether the file writes0888 123 456,+359 888 123 456or00359…. A number that can't be read is kept exactly as written. - A WooCommerce customer report has no phone column. The phones are in the order export, not the customer report - to bring them across, add a "Phone" column to the customer file before you upload it. The report's "Username" column is never mistaken for a phone.
- Imported people get a contact record, not an active password account. If a customer wants to sign in, they do so via "forgot password".
Personal data (GDPR)
You are the controller of this personal data; we process it on your behalf. Only import contacts you have a lawful basis and a data processing agreement to hold - you must confirm this explicitly before the import runs.
The import loads contact records. It does not subscribe anyone by itself - but if your export has a per-contact marketing-consent column and you map it, that consent is carried over, with the opt-in date taken from the source platform. Leave it unmapped and every imported contact stays unsubscribed. Only carry over consent you actually collected.
Newsletter subscribers
Import → Newsletter loads your mailing list from CSV/Excel (e.g. a Shopify, Mailchimp or CloudCart export) - you map the columns, preview a dry run, then confirm. The list becomes the audience your campaigns send to.
- Recognised automatically: Email (the only required column), Name, Language, Status and a subscribed-on date. In-file duplicates are removed by email.
- Status. An address your file marks as unsubscribed (
unsubscribed,cleaned,bounced, "no") imports unsubscribed; an unrecognised status imports as subscribed, with a note in the dry run. - Re-uploading. By default addresses already on your list are skipped. "Update existing" fills in name/language and honours a source unsubscribe - but someone who unsubscribed from you is never re-subscribed by an import.
- Consent (GDPR). Only import people who opted in to hear from you; you confirm this explicitly before the import runs. You are the controller, we send on your behalf, and every subscriber keeps a one-click unsubscribe link.
Orders
Import → Orders loads your order history from CSV/Excel (e.g. an export from your old platform), so your past revenue and each customer's order history are there from day one. It works like the other imports: upload a file, map the columns, preview a dry run, then confirm.
- Order number, email and total are required. Everything else (date, status, payment method, name, phone, address, currency, note, shipping cost, discount, tracking number, UTM campaign columns and the product-line columns) is optional. The date accepts ISO (
2024-03-09) and European day-first (09.03.2024); status and payment method are recognised from free text in English and Bulgarian. - The import is idempotent: each order is keyed by its order number, so re-running the same file skips orders already imported and never duplicates. Repeated numbers within the file are *not* an error - they are the product lines of the same order, and are combined.
- Each order is linked to an existing customer when the email matches (accounts are not auto-created - that's what the customer import is for). When there's no match, the order is still saved with the contact details from the file.
- Missing customer details are filled in from their orders. If a linked customer has no phone, name or address, the import takes them from that customer's orders: the phone and name from the newest order that has them; the address, city and postcode together, from one and the same order. Only empty fields are filled - details the customer already has are never overwritten. This helps when your old platform keeps phones only on orders (a WooCommerce customer report, for example). The order of the two imports doesn't matter: if you import customers after orders, upload the order file again - the orders already imported are skipped, but the profiles are filled.
- Product lines are imported too. In most exports one row is one *product line*, so an order with three products is three rows - the importer combines rows sharing an order number into one order with its product lines. Those lines are saved as a record of what was sold (name, variant, quantity, price); they are linked to a catalogue product when the title matches, and the import never creates products.
- Currency: choose how it's decided. If your export has no currency column and your history spans Bulgaria's switch to the euro, pick "Bulgarian euro changeover" - orders before 1 January 2026 are saved in BGN and orders from that date in EUR, decided per order from its own date. Picking a single currency for a file that spans the switch would mislabel one side of it. An order with no readable date can't be decided and is skipped rather than guessed.
- A Shopify export is recognised automatically. Upload a Shopify
Orders exportand the columns are bound by name, with no guessing. That matters because in such a file the order number lives in a column calledNamewhile the customer is inBilling Name- auto-guessing swapped the two and dropped the product lines. SKUs,Shopify Paymentsas a card payment and the status fromFulfillment Statusare all recognised too (an unfulfilled order stays New, not "Delivered"). - A WooCommerce export is recognised automatically too. Upload an order export from the "Advanced Order Export For WooCommerce" plugin (WooCommerce itself has no order export) and the columns are bound by name: the order total to
Order Total Amount, delivery toOrder Shipping Amount, the product price toItem Cost, and the customer to the billing first and last name joined together (the shipping name when the billing one is empty). WooCommerce statuses are recognised in Bulgarian and English: Completed («Приключена») becomes Delivered; Processing, On hold and Pending payment («Обработка», «Задържана», «Чакащо плащане») become New; Failed, Cancelled and Refunded («Неуспешна», «Отказана», «Възстановена») become Cancelled. A card order's payment follows its status (a failed or pending order is not marked paid). - Phone numbers are saved in the international format (
+359…), like the ones from your checkout; a number that can't be read is kept as written. - The discount is deducted correctly. In some exports (Shopify, WooCommerce) the line prices are full and the discount sits at order level; in others (CloudCart) the lines already have it deducted. The importer knows the difference for recognised formats, so the line total always matches the amount paid.
- Paid card orders are marked as paid. When the file states a payment status it is carried over (paid / refunded / pending). This is what lets migrated card sales appear in your Sales report - without it they would be missing from your turnover. Imported orders do not go into the monthly Приложение 38 file: it lists the orders delivered in the month, the import carries no delivery date, and those months were reported by your previous platform.
- Delivery is worked out from your own numbers. If the order total already includes delivery, it's split out into the shipping cost. If the total matches the products exactly - a free-shipping order where you covered the courier yourself - the shipping cost is saved as 0, so the order isn't understated. If the numbers don't add up either way, the amount the customer actually paid is kept and the order is flagged in the dry run.
Imported orders are inert
They are historic records: they do not send emails, do not register couriers/labels, do not charge anyone, and do not reduce stock.
Personal data (GDPR)
Orders contain personal data. The same rules as customers apply - only import history you have a lawful basis and a data processing agreement to hold, and confirm this explicitly before the import runs.
Redirects (301)
When you move a shop to us, your old URLs change. Without a redirect, your Google-indexed pages return 404 and your ranking collapses. Online store → Redirects builds 301 redirects from the old URLs to their new pages.
An address that starts with a language but does not exist in your shop (for example /en/product/... for a deleted product) shows a "This page doesn't exist" page in your own design - with your menu, search, footer and a button back to the home page - and returns a real 404 code. Old addresses from your previous platform usually have no /en/ in front: without a redirect they show the platform's generic error page, so redirect them.
The fastest route skips this builder
Fill the "Old URL" field in a product or category editor - the redirect is created automatically on save. Products imported with an old-URL column get one automatically too. The builder below is for bulk-matching a whole sitemap / Search Console export at once.
- Set the old URLs on your products and categories. Each old URL is joined to a product or category by its old slug, so without this there is nothing to match against.
- Load your old addresses. Paste your old sitemap URL (most platforms publish one) and/or upload a Google Search Console CSV export of your indexed pages. The two sources are merged.
- Fill in the fixed pages (Home, Contact, FAQ…) under "Old URLs for your pages" on the same screen.
- Review the preview - it shows how many URLs matched and how many are unmatched. Unmatched URLs are not redirected.
- Save. Matched URLs start issuing a true 301 immediately.
Nothing matched - why?
The preview explains the reason: either no product/category has an old URL set, or it has an old URL but no page address (slug) to redirect to. A product needs both - an old URL (to match) and a slug (as the new target).
Active redirects
"Active redirects" lists every live redirect. You can add a one-off by hand (old path → new path), edit, or delete any row. You can also bulk-import from a CSV (columns from,to) - download the template, fill it in, and upload. Before saving you see how many rows are valid and how many are invalid; invalid rows (blank, pointing at the site root, or looping to themselves) are reported, not written. Each row overwrites any existing redirect for the same old path.
Turn redirects on before you switch the domain
Enable them before you point your domain at the new site and organic traffic never breaks for a moment.
Import modes
On import, each section chooses how it's applied, and the preview shows exactly what each mode will do before anything is written:
- Add missing (the default) - imports only the records you don't already have and leaves existing ones untouched. Re-importing the same bundle adds nothing the second time.
- Append - adds every record from the bundle as new (can duplicate on re-import).
- Replace - deletes the existing records of that type and inserts the bundle's. The preview lists every row it will delete, by name, and asks you to confirm before writing. For products it only works in an account with no orders.
The catalogue look applies in every mode. The product card and product page settings (Fast order included) and the low-stock level are one shop-wide setting, not records - so importing the products replaces them with the file's values under "Add missing" too.
A catalogue product you already have also takes its catalogue data from the file under "Add missing" - the catalogue it sells by, its fitment, its Prices & stock table and its personalisation, when the file carries them. A lower stock in that table is recorded in Write-offs as «Correction».
For settings (email branding, legal settings) the choice is:
- Fill blanks - fills only the empty fields, leaving anything you've already set.
- Overwrite - replaces the values outright.
Tips
- Always export a backup first.
- On import, start with "Add missing" or "Append" so you don't lose data.
- Categories are matched by link/name so they aren't duplicated. A match on the name alone only counts under the same parent category, so two subcategories that share a name - say «Girls › Tops» and «Boys › Tops» - stay separate, each with its own products.
- Smart categories travel with their rule - "Best sellers", "Newest", "On sale" and "Biggest discount" carry over and keep filling themselves in the new shop. The exception is a category driven by option-catalogue compatibility: the option catalogue itself travels, but the category's link to the options inside it does not yet - so such a category arrives as a manual one, and you pick its options again there.
Next step
That's the end of the journey. Head back to the Help Center to revisit any phase, or use the ? button on any screen for help with that exact page.