Bulk Recipe Import / Export

Table of Contents


Getting Started

The CSV import/export system is found on the Settings page of your RecipeKit app. From there you can:


  • Download a template CSV with example data
  • Export your existing recipes to CSV
  • Import recipes from a CSV file

The fastest way to get started is to download the template, fill it in with your recipes, and import it.


Downloading the Template

Click Download Template on the Settings page. This gives you a CSV file with:

  • A header row containing all column names
  • One example row showing the correct format for each field

Open the template in a spreadsheet app (Google Sheets, Excel, etc.), use the example as a reference, then delete it and add your own recipes.


CSV Column Reference

Each row in the CSV represents one recipe. The columns are:

Column Required Description
recipe_id No Leave empty for new recipes. Fill with an existing recipe ID to update that recipe.
recipe_title Yes The name of the recipe.
recipe_author No Author name.
recipe_description No Full description text.
recipe_category No Category (e.g., "Dessert", "Main Course").
recipe_cuisine No Cuisine type (e.g., "Italian", "American").
recipe_calories No Calorie count (number).
serving_size No Serving size text (e.g., "4 servings", "24 cookies").
prep_time No Preparation time
cook_time No Cooking time
recipe_image No URL to the recipe's main image
recipe_image_alt_text No Alt text for the main image.
recipe_video No URL to a recipe video.
recipe_note No Additional notes about the recipe.
enable_rating No 1 to enable star ratings, 0 to disable.
blog_id Conditional Shopify blog ID. Required when "Create blog posts" is enabled.
article_id No Existing Shopify article ID to link to.
recipe_tags No Tags separated by semicolons
recipe_ingredients Yes Ingredients separated by semicolons
recipe_equipment No Equipment separated by semicolons
recipe_directions Yes Directions separated by semicolons
direction_images No Image URLs for direction steps
nutrition_data No Nutrition info as key:value pairs
nutrition_template No Nutrition display template name (e.g., "Standard").
nutrition_serving_size No Nutrition serving size text (e.g., "Per cookie").
custom_field_1_key No Label for first custom field.
custom_field_1_value No Value for first custom field.
custom_field_2_key No Label for second custom field.
custom_field_2_value No Value for second custom field.
update_blog_post_tags No 1 to sync tags to the linked blog post, 0 to skip.
update_blog_post_image No 1 to sync the recipe image to the linked blog post, 0 to skip.
status Yes 1 for published, 0 for hidden/draft.

Formatting Rules

Ingredients

Ingredients are separated by semicolons (;).

2 cups flour;1 cup sugar;2 eggs;1 cup butter

Each entry between semicolons becomes one ingredient line in your recipe.


Directions

Directions are separated by semicolons (;). Each entry becomes one numbered step.


Preheat oven to 350F;Cream butter and sugar;Add eggs one at a time;Mix in flour;Bake for 12 minutes


Equipment

Equipment items are separated by semicolons (;).

Large mixing bowl;Whisk;Baking sheet;Parchment paper

Images

Recipe main image (recipe_image column):

Provide a full URL to your image:

https://example.com/images/chocolate-cake.jpg

  • Images already hosted on Shopify's CDN are used directly without re-uploading.
  • Images from external URLs are downloaded and uploaded to your Shopify store automatically.
  • When updating an existing recipe, if the image URL hasn't changed, the upload is skipped.
  • If the image fails to upload, the recipe is still imported (just without the image).

Direction step images (direction_images column):

Provide image URLs separated by semicolons, matched by position to your direction steps in the recipe_directions column. Use an empty entry (no text between semicolons) for steps without images.

https://example.com/step1.jpg;;https://example.com/step3.jpg;

In this example:

  • Step 1 gets step1.jpg
  • Step 2 has no image (empty between semicolons)
  • Step 3 gets step3.jpg
  • Step 4 has no image

The positions in direction_images must match the positions in recipe_directions exactly, including headings. For example, if your directions are:

HEAD:Prep;Preheat oven to 350F;Grease pan;HEAD:Bake;Pour batter;Bake 30 min

Then your direction images should have 6 positions (one per entry, including headings):

;;https://example.com/preheat.jpg;;;https://example.com/baking.jpg

Headings always have empty image positions. When you export recipes that have direction images, they are automatically exported in this format.


Direction images are handled the same way as the main recipe image:

  • Images already on Shopify's CDN or RecipeKit hosting are used directly without re-uploading.
  • External image URLs are uploaded to your Shopify store automatically.
  • When updating an existing recipe, images that match the current step are skipped.
  • If an upload fails, the original URL is kept.

You can link ingredients to Shopify products or external URLs using the double pipe (||) delimiter.


Shopify product linking (recommended):

Use the shopify: prefix followed by the product handle to link an ingredient directly to a product in your store. The product handle is the URL-friendly name from your product's URL (e.g., if your product URL is yourstore.com/products/organic-flour, the handle is organic-flour).


Format: ingredient text||shopify:product-handle


2 cups flour||shopify:organic-flour;1 cup sugar;2 eggs||shopify:free-range-eggs

On import, RecipeKit automatically looks up the product in your Shopify store and attaches the full product data (title, variants, images). This is the same as dragging a product onto an ingredient in the recipe editor. The ingredient becomes a clickable link to the product page and can show the "Add to Cart" button if enabled.


When you export recipes that have Shopify products linked to ingredients, they are automatically exported in this shopify:handle format so they can be re-imported without losing the product connections.


If a product handle is not found in your store during import, the ingredient is still imported but without the product link. A warning is logged.


Plain URL linking:

You can also link to any external URL:


Format: ingredient text||url

2 cups flour||https://yourstore.com/products/organic-flour;1 cup sugar;2 eggs

This makes the ingredient text a clickable link to that URL.


Rules:

  • Only one || per ingredient entry is allowed.
  • The URL or shopify:handle goes after the || (spaces are trimmed).
  • shopify:handle is preferred over plain URLs for products in your own store because it preserves the full product data (variants, images, Add to Cart support).

Section Headings

You can organize ingredients, directions, and equipment into sections using the HEAD: prefix.


Ingredients with headings:

HEAD:Dry Ingredients;2 cups flour;1 cup sugar;1 tsp baking powder;HEAD:Wet Ingredients;2 eggs;1 cup milk;1/2 cup butter

This produces:


Dry Ingredients

  • 2 cups flour
  • 1 cup sugar
  • 1 tsp baking powder

Wet Ingredients

  • 2 eggs
  • 1 cup milk
  • 1/2 cup butter

Directions with headings:

HEAD:Preparation;Preheat oven to 350F;Grease a 9x13 pan;HEAD:Mix Batter;Cream butter and sugar;Add eggs;HEAD:Bake;Pour into pan;Bake for 30 minutes

Equipment with headings:

HEAD:Mixing;Large mixing bowl;Whisk;HEAD:Baking;Baking sheet;Parchment paper

The HEAD: prefix works the same way in all three fields.


Tags

Tags are separated by semicolons (;).

dessert;cookies;chocolate;baking;holiday

Nutrition Data

Nutrition data uses colon-separated key:value pairs, with entries separated by semicolons.


Format: Title:Value;Title:Value

Calories:250;Carbs:30;Fat:12;Protein:3;Sugar:18;Sodium:200

Recognized nutrition titles:

Title Unit
Calories calories
Carbs grams
Fat grams
Protein grams
Sugar grams
Fiber grams
Sodium milligrams
Cholesterol milligrams
Saturated Fat grams
Trans Fat grams
Unsaturated Fat grams

Custom Fields

You can add up to two custom fields per recipe. Both the key and value must be provided together — you cannot have a key without a value or vice versa.

Column Example
custom_field_1_key Difficulty
custom_field_1_value Easy
custom_field_2_key Best Time
custom_field_2_value Afternoon

Time Fields

The prep_time and cook_time columns accept flexible time formats:

Input Interpretation
15 minutes 15 minutes
1 hour 12 minutes 1 hour and 12 minutes
2 hours 2 hours
15 15 minutes (bare numbers are treated as minutes)

Blog Post Connections

To connect recipes to Shopify blog posts:

  • Link to an existing article: Provide both blog_id and article_id.
  • Create a new article: Provide blog_id only (leave article_id empty). You must also enable "Create blog posts" during import.
  • No blog connection: Leave both columns empty.

Use update_blog_post_tags (1 or 0) and update_blog_post_image (1 or 0) to control whether recipe tags and the recipe image are synced to the connected blog post.


Importing Recipes

  1. Go to the Settings page in RecipeKit.
  2. Drag and drop your CSV file into the upload area (or click to browse).
  3. A preview modal appears showing:
    • Matches: Recipes that match existing recipes in your store (by ID or title).
    • New Recipes: Recipes that will be created.
    • Invalid: Rows with errors that will be skipped.
  4. Review the summary. If there are invalid entries, expand the section to see the specific errors and row numbers.
  5. Configure import options (see below).
  6. Click Confirm Import to start.

After confirming, you'll see a progress bar with real-time updates. Processing happens in the background — you can navigate away and return to check progress later.

Import Options

During the preview step, you can toggle:


  • Update existing recipes (default: ON) — Matched recipes are updated with CSV data. When OFF, matched recipes are created as new recipes instead.
  • Create blog posts (default: OFF) — When enabled, recipes with a blog_id but no article_id will have a new Shopify blog article created automatically. Enabling this makes blog_id a required field.

Updating Existing Recipes

There are two ways recipes are matched to existing records:


  1. By recipe_id: If you provide a recipe ID in the recipe_id column, it will match that exact recipe.
  2. By title: If no recipe_id is provided, the system looks for an existing recipe with the same title.

To update recipes, export your current recipes first, modify the CSV, and re-import. The recipe_id column ensures accurate matching.

Cancelling an Import

While an import is in progress, click Stop Import to cancel. Recipes already processed will remain, but no further recipes will be imported.


Exporting Recipes

  1. Go to the Settings page.
  2. Under the export section, select a filter:
    • All recipes
    • Published only (status = 1)
    • Hidden only (status = 0)
  3. Click Export. A CSV file will download to your computer.

The exported CSV uses the exact same format as the import, so you can modify it and re-import to make bulk changes.


Troubleshooting

"recipe_title is required"

Every row must have a value in the recipe_title column. Check for empty rows or rows where the title column was accidentally left blank.


"status must be 0 or 1"

The status column only accepts 0 (hidden) or 1 (published). Any other value will cause the row to be marked invalid.


"blog_id is required when blog post creation is enabled"

If you enabled "Create blog posts" during import, every row must have a valid blog_id. Either provide blog IDs for all rows or disable the "Create blog posts" option.


"Only one || delimiter allowed per ingredient"

An ingredient entry contains more than one ||. Each ingredient can only have one URL link. Check for accidental double pipes in your ingredient text.


"Custom field key provided without value" / "Custom field value provided without key"

Custom fields require both a key and a value. If you provide custom_field_1_key, you must also provide custom_field_1_value (and vice versa).


"recipe_calories must be a valid number"

The recipe_calories field only accepts whole numbers in the range -32,768 to 32,767. Remove any text, commas, or decimal points.


"recipe_ingredients must have at least one ingredient"

The recipe_ingredients column cannot be empty. Provide at least one ingredient.


"recipe_directions must have at least one direction"

The recipe_directions column cannot be empty. Provide at least one direction step.


  • Make sure you're using the correct product handle. The handle is the URL-friendly slug from your product page URL (e.g., organic-flour from yourstore.com/products/organic-flour).
  • The product must exist in your Shopify store. If the handle doesn't match any product, the ingredient is imported without a product link.
  • Product lookups require API access to your store. If your store has API rate limits or connectivity issues, product linking may fail silently.
  • Check that the format is exactly shopify:handle after the || (e.g., 2 cups flour||shopify:organic-flour). Do not include the full URL.

Direction images not appearing after import

  • Ensure the image positions in direction_images align exactly with the positions in recipe_directions, including headings (which should have empty positions).
  • Image URLs must be publicly accessible.
  • The number of semicolons in direction_images should match the number of semicolons in recipe_directions.

Images not appearing after import

  • Verify the image URLs are publicly accessible (not behind a login or paywall).
  • Image uploads can fail silently — the recipe is still imported, just without the image. Re-upload images manually or re-import after fixing the URLs.
  • Images already on Shopify's CDN (cdn.shopify.com) are used directly without re-uploading.

Import seems stuck or slow

  • Recipes are processed with a small delay between each one to avoid overloading Shopify's API (roughly 150ms between recipes, 500ms between batches of 25).
  • Image uploads add additional time per recipe.
  • Large imports (thousands of recipes) can take a while. The progress bar updates in real-time.
  • If you navigate away, your import continues in the background. Return to the Settings page to see progress.

Semicolons in my ingredient/direction text

Since semicolons (;) are used as the delimiter, you cannot use literal semicolons within ingredient or direction text. Rephrase the text to avoid semicolons, or use a comma instead.


Special characters or encoding issues

  • Save your CSV file with UTF-8 encoding.
  • If using Excel, choose "CSV UTF-8 (Comma delimited)" when saving.
  • Values containing commas, double quotes, or newlines should be wrapped in double quotes (most spreadsheet apps do this automatically).

Rows marked as "Invalid" in preview

Expand the invalid entries section in the preview modal to see the specific error for each row, including the row number. Fix the issues in your CSV and re-upload.


Exported CSV looks wrong when opened in Excel

  • Ensure you're opening it as a CSV (not pasting the content).
  • In Excel, use File > Open and select the CSV, or use the Data Import wizard to specify comma as the delimiter and UTF-8 as the encoding.

Import was cancelled but some recipes were already created

Cancelling an import stops future processing but does not roll back recipes that were already created or updated. You can delete unwanted recipes manually from the Recipes page.


What's Next?

  • Creating Recipes - Manual recipe creation
  • Recipe Status and Visibility - Publishing options
  • Linking Blog Posts to Recipes - Blog integration
Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.

Still need help? Contact Us Contact Us