---
url: https://docs.comnto.com/integration/comment-import.md
description: >-
  Importing existing comments from a Disqus XML export or a custom JSON file:
  topic and comment schema, allowed HTML, running the import, and fixing skipped
  comments.
---

# Importing Comments

Bring historical discussions into Comnto by either uploading a Disqus export or providing a JSON file that matches the Comnto import shape. This guide walks through the expected schema, mapping tips, and the end-to-end import flow.

## Supported Source Formats

* **Disqus XML export** – Upload the XML file; if the download is gzipped, extract it to access the `.xml`.
* **Custom JSON** – Normalise any other platform’s export into the structure below. The importer accepts UTF-8 encoded `.json` files and ignores unknown keys.

## JSON Structure Overview

Create a single JSON object with `topics` and `comments` arrays. Topics describe the threads you want to recreate, and comments reference those topics by `topic_id`.

```json
{
  "topics": [],
  "comments": []
}
```

### Topic Fields

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `id` | string | Yes | Stable identifier from your source system. Comments link to this via `topic_id`. |
| `identifier` | string | Yes | Public identifier that Comnto will reuse when the same topic renders on your site (typically an article slug or CMS id). |
| `title` | string | Recommended | Used in the dashboard and moderation tools; defaults to the identifier if omitted. |
| `url` | string | Yes | Canonical URL of the topic. |
| `created_at` | string (ISO 8601) | Recommended | Original creation timestamp of the topic. |

### Comment Fields

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `topic_id` | string | Yes | Must match one of the topic `id` values. Comments referencing unknown topics are skipped. |
| `author_name` | string | Recommended | Display name shown beside the comment. |
| `author_email` | string | Recommended | Needed to match existing user accounts and to preserve gravatars. A placeholder address is fine if you cannot export real emails. |
| `body` | string (HTML) | Yes | Allowed tags: `<p>`, `<strong>`, `<em>`, `<u>`, `<s>`, `<code>`, `<pre>`, `<a>`, `<br>`, `<span>`. Anything else is stripped during sanitisation, so convert advanced formatting (lists, quotes, embeds) into one of the supported tags before exporting. |
| `created_at` | string (ISO 8601) | Recommended | Original publish date. Use UTC or include an explicit offset. |
| `parent_id` | string | Optional | Set to the source comment id to preserve reply chains. Leave empty for top-level comments. |

### Expanded Example

```json
{
  "topics": [
    {
      "id": 123,
      "identifier": "why-comnto-is-awesome",
      "title": "Why Comnto Is Awesome",
      "url": "https://comnto.com/blog/why-comnto-is-awesome",
      "created_at": "2020-07-01T09:00:00Z"
    },
    {
      "id": 456,
      "identifier": "comnto-vs-others",
      "title": "Comnto vs Other Comment Systems",
      "url": "https://comnto.com/blog/comnto-vs-others",
      "created_at": "2020-08-10T15:30:00Z"
    }
  ],
  "comments": [
    {
      "id": 1,
      "topic_id": 123,
      "author_name": "Aiko Tanaka",
      "author_email": "aiko@example.com",
      "body": "<p>Comnto is hands down the best comment system I’ve ever used.</p>",
      "created_at": "2020-07-01T10:12:00Z"
    },
    {
      "id": 2,
      "topic_id": 123,
      "author_name": "Fatima Al-Mansouri",
      "author_email": "fatima@example.com",
      "body": "<p>Absolutely! Comnto feels premium. It’s fast, stable, and looks great.</p>",
      "created_at": "2020-07-01T10:45:00Z",
      "parent_id": 1
    },
    {
      "id": 3,
      "topic_id": 456,
      "author_name": "David Johnson",
      "author_email": "david@example.com",
      "body": "<p>Comnto doesn’t just compete — it dominates.</p>",
      "created_at": "2020-08-10T16:00:00Z"
    }
  ]
}
```

## Preparing Your Export

1. **Extract topics** – Gather the unique thread identifiers, titles, and canonical URLs from your source platform. Normalise slugs so they match the identifiers you will render inside the widget later.
2. **Link comments** – Map each comment to its topic id. When your export lacks a topic reference, derive one from the article URL or slug to avoid mismatches.
3. **Normalise timestamps** – Convert all dates to ISO 8601 strings in UTC. Double-check that time zone offsets match the original data.
4. **Preserve reply order** – Include a stable `parent_id` for replies so nested threads show correctly after import.

## Running the Import

1. **Upload the file** – In the Comnto dashboard, open **Comments → Imports** and upload either the Disqus XML export or your custom JSON file. Large imports may take several minutes to queue.
2. **Monitor progress** – The dashboard shows queued, running, and completed jobs.
3. **Verify the result** – Spot-check a few topics in the moderation UI and on a staging embed. Confirm that identifiers match the slugs you intend to use in production.

If you need assistance importing formats other than Disqus or JSON, share a sample export with support and they will advise on the quickest mapping approach.

## Validation Checklist

* File is valid JSON (double quotes, UTF-8 encoding, no trailing commas).
* Every comment `topic_id` exists in `topics`.
* HTML in `body` only contains safe tags; scripts and inline event handlers have been removed.

## Troubleshooting

* **Import skipped comments** – Unsupported HTML tags are stripped during sanitisation; if the body becomes empty, or if a comment lacks a `topic_id` or references an unknown topic, the import omits it.
* **Replies appear as top-level comments** – Keep each reply's original `parent_id` pointing to another comment in the payload, and sort comments oldest first so parents always precede their replies.
* **Duplicate topics after embedding** – Match the JSON `identifier` to the widget's `data-topic` (or API `topic`) value; mismatches create separate threads.
