{"_id":"59365227e16643001bac504f","category":{"_id":"59365227e16643001bac5034","version":"59365226e16643001bac5030","project":"543026235eceb608003fde5f","__v":0,"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2016-09-19T11:41:31.988Z","from_sync":false,"order":3,"slug":"test","title":"Advanced"},"project":"543026235eceb608003fde5f","user":"5736eb0b1a48812200566f0d","parentDoc":null,"version":{"_id":"59365226e16643001bac5030","project":"543026235eceb608003fde5f","__v":1,"createdAt":"2017-06-06T06:56:38.999Z","releaseDate":"2017-06-06T06:56:38.999Z","categories":["59365227e16643001bac5031","59365227e16643001bac5032","59365227e16643001bac5033","59365227e16643001bac5034"],"is_deprecated":false,"is_hidden":false,"is_beta":true,"is_stable":true,"codename":"","version_clean":"1.0.0","version":"1.0.0"},"__v":0,"updates":[],"next":{"pages":[],"description":""},"createdAt":"2017-06-05T13:05:59.180Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":4,"body":"Ghost imports from existing blogs via a custom JSON data format, which is described [below](#section-json-file-structure). The import and export tools can be found on the 'labs' page in Ghost settings. The importer will accept a JSON file, markdown file, an image, or a zip file containing a combination of either JSON or markdown files along with accompanying images.\n\n## Existing Plugins\n\n### Official\n* WordPress users can use the [Ghost WordPress Plugin](http://wordpress.org/plugins/ghost/) to export their data.\n\n### Non-official\n* WordPress users can also use the [wp2ghost](https://github.com/jonhoo/wp2ghost) command-line tool to convert their WordPress export files to Ghost-compatible JSON.\n* Jekyll users can use the [Jekyll to Ghost Plugin](https://github.com/redwallhp/Jekyll-to-Ghost)\n* Blogger users can try [blogger2ghost](https://github.com/bebraw/blogger2ghost). Also available as a [web service](http://blogger2ghost.com/).\n* Open-source geeks may consider importing READMEs from all of their Github repositories as regular posts using [gh2ost](https://github.com/RReverser/gh2ost) tool.\n* Tumblr users can use [Tumblr to Ghost](https://github.com/jpadilla/tumblr-to-ghost)\n\n## Importing the JSON\nOnce you've generated the JSON go to the Labs Menu (`/ghost/settings/labs/`) on your blog to access the import form.\n\n## Rolling your own\n\nIf no export tools exist for your current blogging system you'll need to create one that generates a JSON file as described here. There is a full example at the end of this file. Please note that your final JSON file should have no comments in the final format. Those are only included here for readability and explanatory purposes.\n\n### JSON file structure\n\nFirst and foremost, your JSON file must contain valid JSON. You can test your file is valid using the [JSONLint](http://jsonlint.com/) online tool.\n\nThe file structure can optionally be wrapped in: \n\n```\n{\n  \"db\": [...contents here...]\n}\n``` \n\nBoth with and without are valid Ghost JSON files. But you must include a `meta` and a `data` object.\n\nIDs inside the file are usually relative to the file only, so if you have a `post` with `id: 1` and a `posts_tags` object which references `post_id: 1`, then those two things will be linked, but they do not relate to the `post` with `id: 1` in your database. \n\n#### The meta object\n\n```\n\"meta\": {\n    \"exported_on\":1408552443891,\n    \"version\":\"003\"\n}\n```\n\nThe `meta` block expects two keys, `exported_on` and `version`. `exported_on` should be an epoch timestamp in milliseconds, version should be the data version the import is valid for. Currently Ghost is on data version 003, see [version info](https://github.com/TryGhost/Ghost/wiki/Version-Info) for more details.\n\n#### The data block\n\n```\n\"data\": { \n  \"posts\": [{...}, ...], \n  \"tags\": [], \n  \"posts_tags\": [], \n  \"users\": [], \n  \"roles_users\": []\n}\n```\n\nThe data block contains all of the posts, tags, and users that you want to import into your blog, as well as relationships between posts and tags and users and roles. Each item that you include should be an array of objects.\n\n#### Users\n\nWith 0.5 comes the ability to import multiple users into your blog. Any user in the file who has an email address which matches the email address of a user already in your database will be ignored. Any user with a new email address will be imported and their account set to locked so that they must reset their password to login.\n\n##### Linking objects to users\n\nIf you want to link your posts, tags, etc to the user they were authored/created/published by you can do so by specifying a user id relative to a user's id in the import file. So, if you have a user with `id: 2` in your file, and a post with `author_id: 2` that post will be set to be authored by that user.\n\nAll new users (i.e. users with email addresses that aren't yet present in the db) are imported first. Then the importer matches the ids from `created_by`, `author_id` etc with users in the `users: []` object, and finally maps them to the right user in the database via their email address. Therefore if you want to link objects to a user that is already in the database you can specify the bare minimum information for that user so that it can be mapped correctly:\n\n```\n\"users\": [{\n   id: 3,\n   name: \"A User\",\n   email: \"user:::at:::example.com\"\n}]\n```\n\n**Note:** there is a special case for user ids. Any reference to a user with `id: 1`, i.e. `created_by: 1` or `author_id: 1` where there is no user with that id in the import file, will be assumed to refer to the user who has the `owner` role.\n\n##### User Roles\n\nAll users are given the role of `author` by default. If you want to specify different roles, you can do so by providing a `roles_users` object, much like the `posts_tags` object. Please note that Ghost doesn't yet support importing roles, so in this case the `role_id` is always relative to the `id` in the database, rather than in the file. This will change to match the other objects in the near future.\n\n```\n{\n    \"meta\":{\n        // epoch time in milliseconds\n        \"exported_on\":  1388805572000,\n        // Data version, current is 003\n        \"version\":      \"003\"\n\n    },\n    \"data\":{\n        \"posts\": [\n            {\n                \"id\":5,\n                \"title\":        \"my blog post title\",\n                \"slug\":         \"my-blog-post-title\",\n                \"markdown\":     \"the *markdown* formatted post body\",\n                \"html\":         \"the <i>html</i> formatted post body\",\n                \"image\":        null,\n                \"featured\":     0, // boolean indicating featured status\n                \"page\":         0, // boolean indicating if this is a page or post\n                \"status\":       \"published\", // or draft\n                \"language\":     \"en_US\",\n                \"meta_title\":   null,\n                \"meta_description\":null,\n                \"author_id\":    1, // the first user created has an id of 1\n                \"created_at\":   1283780649000, // epoch time in millis\n                \"created_by\":   1, // the first user created has an id of 1\n                \"updated_at\":   1286958624000, // epoch time in millis\n                \"updated_by\":   1, // the first user created has an id of 1\n                \"published_at\": 1283780649000, // epoch time in millis\n                \"published_by\": 1 // the first user created has an id of 1\n            }\n        ],\n        \"tags\": [\n            {\n                \"id\":           3,\n                \"name\":         \"Colorado Ho!\",\n                \"slug\":         \"colorado-ho\",\n                \"description\":  \"\"\n            },\n            {\n                \"id\":           4,\n                \"name\":         \"blue\",\n                \"slug\":         \"blue\",\n                \"description\":  \"\"\n            }\n        ],\n        \"posts_tags\": [\n            {\"tag_id\":3, \"post_id\":5},\n            {\"tag_id\":3, \"post_id\":2},\n            {\"tag_id\":4, \"post_id\":24}\n        ],\n        \"users\": [\n            {\n                \"id\":           2,\n                \"name\":         \"user's name\",\n                \"slug\":         \"users-name\",\n                \"email\":        \"user@example.com\",\n                \"image\":        null,\n                \"cover\":        null,\n                \"bio\":          null,\n                \"website\":      null,\n                \"location\":     null,\n                \"accessibility\": null,\n                \"status\":       \"active\",\n                \"language\":     \"en_US\",\n                \"meta_title\":   null,\n                \"meta_description\": null,\n                \"last_login\":   null,\n                \"created_at\":   1283780649000, // epoch time in millis\n                \"created_by\":   1, // the first user created has an id of 1\n                \"updated_at\":   1286958624000, // epoch time in millis\n                \"updated_by\":   1 // the first user created has an id of 1\n            }\n        ],\n        \"roles_users\": [\n            {\n                \"user_id\": 2,\n                \"role_id\": 3   \n            }\n        ]\n    }\n}\n```\n\n### Importing Images\n\nGhost can import images which match any of the formats [accepted by the API](https://github.com/TryGhost/Ghost/blob/lts/core/server/config/index.js#L188). Multiple images can be imported with a zip file. \nWhen uploading a zip which includes both images and a JSON or markdown file, the relative path to the images from the JSON should match any relative path used inside the JSON/markdown data. Ghost will then attempt to update the image paths in the content of the JSON/markdown such that they will continue to work after importing.\n\nE.g. If your JSON or markdown contains an image path like `/images/my-image.jpg` then ensure there is a directory called `images` inside the zip file, next to the JSON/markdown files, which contains your `my-image.jpg` file, and the import should keep images in tact.\n\n### Importing Markdown\n\nGhost can import markdown files and convert them into posts. Ghost expects the markdown files to have a name like:\n\n`status-year-month-day-slug.markdown`\n\nE.g.\n\n`published-2015-04-01-april-fools.markdown`\n\nIf the post is published, the date provided will be used as the publish date. The slug will be used as the URL for the post.\n\nThe content of the file will be used as the content of the post, with the following special rules:\n\n- If the first thing in the post is markdown for an image (e.g. `![](my/image/url.jpg)`, this will be used as the posts cover image.\n- If the first thing in the post, or the second thing after an image, is a level 1 heading (e.g. `# My heading`) this will be used as the posts title (falls back to the slug).\n\nImages can be imported with markdown files by including them together inside a zip file and ensuring the relative paths matched, as explained above.\n\nYou can import multiple markdown files inside a single zip.\n\n## Troubleshooting Ghost Imports\n\nThe Ghost importer takes a JSON file to import data. It has been improved to make it far more robust and provide greater information about the status of your import. \n\nThere are a number of ways in which an import file may trigger an **Error** or a **Warning** particularly if the the JSON file was not created by Ghost but by a third-party tool.\n\n### Error\n\nWhen Ghost detects an error, the import will be cancelled, no information is imported and there should be a suitable error message to help you debug the problem. This also means there may be multiple errors in your import file but you will only see a single error during the import process.\n\nAn Error or warning should contain a relevant message on why the import was not successful along with a the relevant JSON entry that caused the issue where applicable.\n\nAn example of an error would be a JSON file that contains a null email field.\n\nExample:\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/e56ea53-ScreenShot2017-06-06at18.48.05.png\",\n        \"Screen+Shot+2017-06-06+at+18.48.05.png\",\n        1821,\n        530,\n        \"#f1f7f8\"\n      ],\n      \"caption\": \"Import Error\"\n    }\n  ]\n}\n[/block]\n### Warning\n\nYour blog may contain multiple warnings. These are issues that may want to know about but are not significant enough to prevent the data being imported. Examples of this include a duplicate user (either duplicated in your JSON file or matching an existing user) or a post linked to an unknown user. \n\nExample:\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/54cc472-ScreenShot2017-06-06at19.00.36.png\",\n        \"Screen+Shot+2017-06-06+at+19.00.36.png\",\n        1653,\n        604,\n        \"#f2f6f8\"\n      ],\n      \"caption\": \"Import Warning\"\n    }\n  ]\n}\n[/block]","excerpt":"","slug":"the-importer","type":"basic","title":"The Importer"}
Ghost imports from existing blogs via a custom JSON data format, which is described [below](#section-json-file-structure). The import and export tools can be found on the 'labs' page in Ghost settings. The importer will accept a JSON file, markdown file, an image, or a zip file containing a combination of either JSON or markdown files along with accompanying images. ## Existing Plugins ### Official * WordPress users can use the [Ghost WordPress Plugin](http://wordpress.org/plugins/ghost/) to export their data. ### Non-official * WordPress users can also use the [wp2ghost](https://github.com/jonhoo/wp2ghost) command-line tool to convert their WordPress export files to Ghost-compatible JSON. * Jekyll users can use the [Jekyll to Ghost Plugin](https://github.com/redwallhp/Jekyll-to-Ghost) * Blogger users can try [blogger2ghost](https://github.com/bebraw/blogger2ghost). Also available as a [web service](http://blogger2ghost.com/). * Open-source geeks may consider importing READMEs from all of their Github repositories as regular posts using [gh2ost](https://github.com/RReverser/gh2ost) tool. * Tumblr users can use [Tumblr to Ghost](https://github.com/jpadilla/tumblr-to-ghost) ## Importing the JSON Once you've generated the JSON go to the Labs Menu (`/ghost/settings/labs/`) on your blog to access the import form. ## Rolling your own If no export tools exist for your current blogging system you'll need to create one that generates a JSON file as described here. There is a full example at the end of this file. Please note that your final JSON file should have no comments in the final format. Those are only included here for readability and explanatory purposes. ### JSON file structure First and foremost, your JSON file must contain valid JSON. You can test your file is valid using the [JSONLint](http://jsonlint.com/) online tool. The file structure can optionally be wrapped in: ``` { "db": [...contents here...] } ``` Both with and without are valid Ghost JSON files. But you must include a `meta` and a `data` object. IDs inside the file are usually relative to the file only, so if you have a `post` with `id: 1` and a `posts_tags` object which references `post_id: 1`, then those two things will be linked, but they do not relate to the `post` with `id: 1` in your database. #### The meta object ``` "meta": { "exported_on":1408552443891, "version":"003" } ``` The `meta` block expects two keys, `exported_on` and `version`. `exported_on` should be an epoch timestamp in milliseconds, version should be the data version the import is valid for. Currently Ghost is on data version 003, see [version info](https://github.com/TryGhost/Ghost/wiki/Version-Info) for more details. #### The data block ``` "data": { "posts": [{...}, ...], "tags": [], "posts_tags": [], "users": [], "roles_users": [] } ``` The data block contains all of the posts, tags, and users that you want to import into your blog, as well as relationships between posts and tags and users and roles. Each item that you include should be an array of objects. #### Users With 0.5 comes the ability to import multiple users into your blog. Any user in the file who has an email address which matches the email address of a user already in your database will be ignored. Any user with a new email address will be imported and their account set to locked so that they must reset their password to login. ##### Linking objects to users If you want to link your posts, tags, etc to the user they were authored/created/published by you can do so by specifying a user id relative to a user's id in the import file. So, if you have a user with `id: 2` in your file, and a post with `author_id: 2` that post will be set to be authored by that user. All new users (i.e. users with email addresses that aren't yet present in the db) are imported first. Then the importer matches the ids from `created_by`, `author_id` etc with users in the `users: []` object, and finally maps them to the right user in the database via their email address. Therefore if you want to link objects to a user that is already in the database you can specify the bare minimum information for that user so that it can be mapped correctly: ``` "users": [{ id: 3, name: "A User", email: "user@example.com" }] ``` **Note:** there is a special case for user ids. Any reference to a user with `id: 1`, i.e. `created_by: 1` or `author_id: 1` where there is no user with that id in the import file, will be assumed to refer to the user who has the `owner` role. ##### User Roles All users are given the role of `author` by default. If you want to specify different roles, you can do so by providing a `roles_users` object, much like the `posts_tags` object. Please note that Ghost doesn't yet support importing roles, so in this case the `role_id` is always relative to the `id` in the database, rather than in the file. This will change to match the other objects in the near future. ``` { "meta":{ // epoch time in milliseconds "exported_on": 1388805572000, // Data version, current is 003 "version": "003" }, "data":{ "posts": [ { "id":5, "title": "my blog post title", "slug": "my-blog-post-title", "markdown": "the *markdown* formatted post body", "html": "the <i>html</i> formatted post body", "image": null, "featured": 0, // boolean indicating featured status "page": 0, // boolean indicating if this is a page or post "status": "published", // or draft "language": "en_US", "meta_title": null, "meta_description":null, "author_id": 1, // the first user created has an id of 1 "created_at": 1283780649000, // epoch time in millis "created_by": 1, // the first user created has an id of 1 "updated_at": 1286958624000, // epoch time in millis "updated_by": 1, // the first user created has an id of 1 "published_at": 1283780649000, // epoch time in millis "published_by": 1 // the first user created has an id of 1 } ], "tags": [ { "id": 3, "name": "Colorado Ho!", "slug": "colorado-ho", "description": "" }, { "id": 4, "name": "blue", "slug": "blue", "description": "" } ], "posts_tags": [ {"tag_id":3, "post_id":5}, {"tag_id":3, "post_id":2}, {"tag_id":4, "post_id":24} ], "users": [ { "id": 2, "name": "user's name", "slug": "users-name", "email": "user@example.com", "image": null, "cover": null, "bio": null, "website": null, "location": null, "accessibility": null, "status": "active", "language": "en_US", "meta_title": null, "meta_description": null, "last_login": null, "created_at": 1283780649000, // epoch time in millis "created_by": 1, // the first user created has an id of 1 "updated_at": 1286958624000, // epoch time in millis "updated_by": 1 // the first user created has an id of 1 } ], "roles_users": [ { "user_id": 2, "role_id": 3 } ] } } ``` ### Importing Images Ghost can import images which match any of the formats [accepted by the API](https://github.com/TryGhost/Ghost/blob/lts/core/server/config/index.js#L188). Multiple images can be imported with a zip file. When uploading a zip which includes both images and a JSON or markdown file, the relative path to the images from the JSON should match any relative path used inside the JSON/markdown data. Ghost will then attempt to update the image paths in the content of the JSON/markdown such that they will continue to work after importing. E.g. If your JSON or markdown contains an image path like `/images/my-image.jpg` then ensure there is a directory called `images` inside the zip file, next to the JSON/markdown files, which contains your `my-image.jpg` file, and the import should keep images in tact. ### Importing Markdown Ghost can import markdown files and convert them into posts. Ghost expects the markdown files to have a name like: `status-year-month-day-slug.markdown` E.g. `published-2015-04-01-april-fools.markdown` If the post is published, the date provided will be used as the publish date. The slug will be used as the URL for the post. The content of the file will be used as the content of the post, with the following special rules: - If the first thing in the post is markdown for an image (e.g. `![](my/image/url.jpg)`, this will be used as the posts cover image. - If the first thing in the post, or the second thing after an image, is a level 1 heading (e.g. `# My heading`) this will be used as the posts title (falls back to the slug). Images can be imported with markdown files by including them together inside a zip file and ensuring the relative paths matched, as explained above. You can import multiple markdown files inside a single zip. ## Troubleshooting Ghost Imports The Ghost importer takes a JSON file to import data. It has been improved to make it far more robust and provide greater information about the status of your import. There are a number of ways in which an import file may trigger an **Error** or a **Warning** particularly if the the JSON file was not created by Ghost but by a third-party tool. ### Error When Ghost detects an error, the import will be cancelled, no information is imported and there should be a suitable error message to help you debug the problem. This also means there may be multiple errors in your import file but you will only see a single error during the import process. An Error or warning should contain a relevant message on why the import was not successful along with a the relevant JSON entry that caused the issue where applicable. An example of an error would be a JSON file that contains a null email field. Example: [block:image] { "images": [ { "image": [ "https://files.readme.io/e56ea53-ScreenShot2017-06-06at18.48.05.png", "Screen+Shot+2017-06-06+at+18.48.05.png", 1821, 530, "#f1f7f8" ], "caption": "Import Error" } ] } [/block] ### Warning Your blog may contain multiple warnings. These are issues that may want to know about but are not significant enough to prevent the data being imported. Examples of this include a duplicate user (either duplicated in your JSON file or matching an existing user) or a post linked to an unknown user. Example: [block:image] { "images": [ { "image": [ "https://files.readme.io/54cc472-ScreenShot2017-06-06at19.00.36.png", "Screen+Shot+2017-06-06+at+19.00.36.png", 1653, 604, "#f2f6f8" ], "caption": "Import Warning" } ] } [/block]