Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Demo of importing a CSV file into a Contentful space
first name last name age
Stephen Sugden 31
Tom Reznik 29
Justin Thomas 30
#!/usr/bin/env babel-node --stage=0
import fs from 'fs';
import contentful from 'contentful-management';
import Parser from 'csv-parse';
import prat from 'prat';
const client = contentful.createClient({
/**
* Your Management API token. Get one quickly at
* contentful.com/developers/documentation/content-management-api
* then set it as an environment variable like
*
* export CONTENTFUL_CMA_TOKEN="abcdef123457890"
*/
accessToken: process.env.CONTENTFUL_CMA_TOKEN,
});
/**
* The Content Type ID that matches the rows from the CSV you want to import
*/
const contentTypeId = '5aL1iEoPWE44KAcwUOw8M6';
async function main () {
const space = await client.getSpace('n65xuot4ik7f');
const parser = new Parser({columns: true});
const rows = fs.createReadStream('./data.csv').pipe(parser);
const entries = await prat.ify(rows)
.map((row) => rowToEntry(space, row))
.reduce([], (entries, entry) => entries.concat(entry));
console.log('entries', entries)
}
/**
* Finds an entry and updates it, or creates a new entry if no existing entry is found.
*
* The update logic simply overwrites the existing fields, a deep merge would
* be a better strategy if the entries also have fields that are edited by humans.
*/
async function rowToEntry (space, row) {
const id = `${row['first name']}.${row['last name']}`;
const sys = { id };
const fields = rowToFields(row);
try {
const entry = await space.getEntry(id)
entry.fields = fields;
console.log('Update', id);
return await space.updateEntry(entry);
} catch (_) {
console.log('Create', id);
return await space.createEntry(contentTypeId, { sys, fields });
}
}
/**
* This helper maps a CSV row to the contentful fields structure.
* Currently it's hard-coded to use en-US, but expanding this script to support
* multiple locales (maybe by importing different files) would be trivial.
*/
function rowToFields (row) {
return {
firstName: { 'en-US': row['first name'] },
lastName: { 'en-US': row['last name'] },
age: { 'en-US': parseInt(row['age'], 10) }
};
}
main().catch((err) => {
console.error(err.stack);
process.exit(1);
});
{
"name": "example-contentful-csv-import",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Tests? maybe next time ;)\" && exit 1",
"import": "babel-node --stage=0 index.js"
},
"author": "Stephen Sugden",
"license": "MIT",
"dependencies": {
"babel": "^5.5.8",
"contentful-management": "^0.1.1",
"csv": "^0.4.5",
"prat": "^1.1.0"
}
}
@duffy-walsh

This comment has been minimized.

Copy link

@duffy-walsh duffy-walsh commented Apr 6, 2017

In case anyone is a late comer to this like myself, the value of the contentTypeId should be the human readable form. For example, instead of something like '5aL1iEoPWE44KAcwUOw8M6', it should be 'person' or the corresponding value.

@ralphilius

This comment has been minimized.

Copy link

@ralphilius ralphilius commented Aug 12, 2017

Other note, you need to use babel-cli to compile the code so that it can be run with node 6.x.x. Otherwise, run it with babel-node

@rtuttlecoder

This comment has been minimized.

Copy link

@rtuttlecoder rtuttlecoder commented Apr 13, 2021

how does one properly format an Array or RichText for this csv import?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment