Blog articles

One row creates one article in the blog you choose. The natural fit for moving a blog into Shopify from WordPress, Ghost, Webflow or a spreadsheet.

Read this before you import twice

Articles are the one import type with no duplicate detection and no pre-import check. Shopify doesn't treat articles as uniquely keyed, so ImportKit can't reliably tell “this article again” from “a new article with a similar title”. Running the same file twice creates the articles twice, and there's no undo. Import a five-row sample first.

Choose the blog

Blog articles need a target: which blog the articles go into. Pick it on the upload step, above the drop zone. The first 50 blogs in your store are offered — more than any store needs in practice.

No blogs listed? Create one in the Shopify admin under Online Store → Blog posts first. ImportKit imports articles, not blogs.

One import writes to one blog. To split articles across blogs, split the file and run one import per blog.

A worked example

articles.csv
title,body_html,author,tags,handle,summary_html
Choosing the right size,"<p>Our sizes run true to fit.</p>",Jane Doe,"guides, sizing",choosing-the-right-size,A short sizing guide.
Caring for your order,"<p>Wash cold, dry flat.</p>",John Roe,"guides, care",caring-for-your-order,How to keep things looking new.

Two articles, two credits.

Standard columns

Only title is genuinely required — a row without one fails with No title found for this row.

ColumnFieldNotes
title Required Title The article headline.
body_html Body (HTML) The article content as HTML. Quote the cell — it will contain commas, and probably line breaks.
author Author A plain name string, not a reference to a Shopify user.
summary_html Summary (HTML) The excerpt shown in blog listings. Plain text is fine.
handle Handle / Slug The URL segment. Shopify generates one from the title if you leave it out — but supply your own if you're preserving existing URLs.
tags Tags Comma-separated in one cell: "guides, sizing". Quote the cell.
published_at Published At The publication date, so a migrated archive keeps its chronology. ISO 8601: 2024-03-18T09:00:00Z.
image_url Featured Image URL A publicly reachable URL. Shopify fetches and hosts the image, so the source must be accessible at import time.
template_suffix Template Suffix For an alternate theme template — article.feature means a suffix of feature.
Articles are always published

There's no draft or status column for article imports. Every imported article is created published. If you need drafts, import into a blog that isn't linked from your navigation, review there, and move them afterwards — or accept that they'll be live and import in small batches.

Article metafields in the same row

This is the part that makes article imports more than a title-and-body exercise. If your store has metafield definitions whose owner type is ARTICLE, they show up on the mapping step alongside the standard fields, keyed namespace.key.

articles-with-metafields.csv
title,body_html,author,custom.reading_time,custom.written_by
Materials we use,"<p>Only recycled fibres.</p>",Jane Doe,4,jane-doe

Here custom.reading_time is a number_integer metafield and custom.written_by is a metaobject_reference pointing at an author entry.

Import your article metafield definitions first, then use Refresh fields on the mapping step if you created them while the wizard was open. The first 100 article metafield definitions are offered for mapping.

Metaobject references in article rows

A metaobject reference column is unusually forgiving here. ImportKit will match on:

Matching is case-insensitive, so JANE DOE resolves too.

Two constraints
  • Lookups search the first 250 entries of the referenced type. Past that, use a full gid://shopify/Metaobject/… value.
  • Reference lists are comma-separated only in article imports. A newline-separated cell won't resolve.

An unresolved value doesn't fail the row. The article is still created, and you get a warning on that row: custom.written_by: no metaobject entry matches "Jane Do", so it was left out. Warnings appear in the job results in Jobs, so check there after a migration.

No pre-import check, no conflict mode

Because articles aren't uniquely keyed, step 3 for this import type is a preview rather than a check: it shows how the first row maps to Shopify fields, as a last sanity check on your mapping. There's no per-row verdict, no credit estimate and no conflict mode.

What to do instead:

Screenshot

Step 3 — Preview mapped data

The blog-article preview table with its three columns — Shopify Field, CSV Column, Value — showing the first row.

assets/screenshots/articles-preview.png

Migrating a blog from elsewhere

  1. Export from your current platform

    You want, at minimum, title, HTML body, author, tags, slug and publication date. WordPress exports XML — convert it to CSV with any of the common plugins or a script. Keep the HTML body intact rather than converting it to plain text.

  2. Preserve your URLs

    Map your existing slug to handle. Shopify article URLs are /blogs/<blog-handle>/<article-handle>, so the path won't match your old site exactly — set up redirects in Shopify for the old paths.

  3. Check the images

    image_url is fetched by Shopify at import time, so the URLs must still be publicly reachable. Import before you take the old site down. Images embedded in body_html are not re-hosted — they stay as absolute URLs pointing at wherever they are now, so plan to rewrite those or keep the old media host alive.

  4. Import definitions first if you're adding metafields

    Reading time, related products, SEO fields — create those definitions with owner type ARTICLE before the article import, so the columns are available to map.

  5. Sample, then run

    Five rows, check them in the admin, then import the rest. Remember there's no de-duplication, so don't re-run the sample rows as part of the full file — remove them.

Common problems

The body arrived as escaped HTML tags shown as text
Your export escaped the HTML before writing the CSV (&lt;p&gt; instead of <p>). Unescape it in the source file — ImportKit passes the cell through as given.
Every article is on one line, or the file has too few rows
Multi-line HTML bodies weren't quoted in the export. Each body containing a line break must be wrapped in double quotes. Quoting rules →
Tags became one long tag
Check the cell really is "guides, sizing" and not "guides;sizing". Tags split on commas.
Featured images are missing
The URL wasn't reachable when the import ran — a private staging URL, an expired signed URL, or a host requiring authentication. Fix the URLs and set the values with a metafield values import, or in the admin.
The publication date is today, not the original date
The published_at column wasn't mapped, or its format wasn't ISO 8601. Use 2024-03-18T09:00:00Z.
I imported twice and now have duplicates
Delete the extras in the Shopify admin — ImportKit can't. Open the job in Jobs; every successful row lists the Shopify ID it created, which tells you exactly which articles came from that run.

Next