DiscussionForumPosting schema: marking up forum threads and replies

DiscussionForumPosting marks up an original post in a user-driven discussion, with the replies nested beneath it as Comment items. Google needs three things for each post: an author with a name, a datePublished, and the content itself as text, image or video.

The point is recognition. When forum pages say plainly who wrote each post, when, and how the conversation branches, Google can tell a real community thread from an article with a comment box, and it draws on that in results like Discussions and forums. If your threads are mostly one question followed by answers, QAPage is the better fit.

JSON-LD example

Copy this into a <script type="application/ld+json"> tag and replace the values with your own.

json
{
  "@context": "https://schema.org",
  "@type": "DiscussionForumPosting",
  "headline": "Finally flattened my warped cherry panel (pictures inside)",
  "text": "After two failed attempts with clamps, I wet the concave side, left it cupped-side down on the lawn in the sun for an hour, then stickered it under weights for four days. It came out within a sixteenth.",
  "url": "https://example.com/forum/topic/warped-cherry-panel/",
  "datePublished": "2026-09-12T16:20-04:00",
  "author": {
    "@type": "Person",
    "name": "Marta Quill",
    "url": "https://example.com/forum/users/mquill/"
  },
  "isPartOf": "https://example.com/forum/board/wood-movement/",
  "image": "https://example.com/wp-content/uploads/forum/cherry-panel-after.jpg",
  "interactionStatistic": [
    {
      "@type": "InteractionCounter",
      "interactionType": "https://schema.org/LikeAction",
      "userInteractionCount": 31
    },
    {
      "@type": "InteractionCounter",
      "interactionType": "https://schema.org/CommentAction",
      "userInteractionCount": 2
    }
  ],
  "comment": [
    {
      "@type": "Comment",
      "text": "Did you seal the end grain afterward? Mine cupped right back within a month.",
      "datePublished": "2026-09-12T18:02-04:00",
      "author": {
        "@type": "Person",
        "name": "benchdog",
        "url": "https://example.com/forum/users/benchdog/"
      },
      "comment": [
        {
          "@type": "Comment",
          "text": "Yes, shellac on both faces the same day. That was the missing step last time.",
          "datePublished": "2026-09-12T19:45-04:00",
          "author": {
            "@type": "Person",
            "name": "Marta Quill",
            "url": "https://example.com/forum/users/mquill/"
          }
        }
      ]
    }
  ]
}

Properties

PropertyStatusWhat it is
authorRequiredThe Person or Organization that wrote the post, with author.name.
datePublishedRequiredWhen the post went up, in ISO 8601 with a time zone offset.
text, image or videoRequiredAt least one, carrying the post's content. Not needed when the item only points to a post that lives on another page, as on category listings or later thread pages.
headlineRecommendedThe thread title, when the forum has one. Don't invent one by cutting off the first line of text.
urlRecommendedThe discussion's canonical URL. For a thread spread over several pages, use the first page.
commentRecommendedReplies as Comment items, in the order they appear. Threaded forums nest comments inside comments.
interactionStatisticRecommendedCounts using LikeAction, DislikeAction, ViewAction, CommentAction or ReplyAction, and ShareAction.
isPartOfRecommendedThe subforum or group the thread belongs to, as a URL or a CreativeWork with url.
sharedContentRecommendedWhat the post shares: a WebPage for a link, an ImageObject or VideoObject, or a quoted post or Comment.
creativeWorkStatusRecommendedSet to Deleted for a removed post kept in place so replies still make sense.
author.url / digitalSourceTypeRecommendedA link to the poster's profile page, and a flag for machine-written posts.

Threads, trees and page two

Match the markup to how the forum actually displays replies.

  • Threaded forums (replies to replies) nest comment inside comment, building a tree like the one in the example.
  • Linear forums (one opening post, then replies in order) put every reply directly under the original post.
  • Long threads split across pages keep the same url value, the first page, on every page. Later pages can refer to the opening post by URL instead of repeating its text.

Mark up every post that appears on the page, in the same order readers see it. If some replies aren't marked up, commentCount tells Google how many exist.

A rare case where Google prefers microdata

For most types, Google recommends JSON-LD. For forums it suggests microdata or RDFa where possible, because a JSON-LD block has to repeat the full text of every post, which adds a lot of weight to a long thread. JSON-LD is still fully supported; this is a recommendation, not a requirement.

On WordPress, microdata means adding itemscope and itemprop attributes in the forum's templates. bbPress, for example, lets a theme override its template files by copying them into a bbpress folder in the theme, which is where those attributes would go. If template edits aren't practical, JSON-LD is fine; just make sure it includes each post's entire text, as Google asks, not a trimmed excerpt.

Forum, social feed or something else?

Google limits this type to posts written by users. Its own examples help:

  • Use it for a community forum about a game, a general forum platform with many subforums, or a social platform where people post and reply.
  • Don't use it for an article or blog post written by the site or its agents, even with a busy comment section, or for user reviews of a product. Those have their own types: Article and review snippets.

A site that works more like a social network than a forum can use SocialMediaPosting, the parent type, with the same requirements. Leave out headline there.

Printing it from a WordPress forum

Check what your forum plugin already outputs before adding anything; view the source of a thread and search for DiscussionForumPosting. If the plugin prints nothing, generate the markup from the topic and its replies and append it through Hydrogen SEO:

php
add_filter( 'hydrogen_seo_schemas', function ( $schemas ) {
    if ( is_singular( 'topic' ) ) {
        $schemas[] = my_forum_thread_schema( get_queried_object_id() ); // Returns the array shown in the example.
    }
    return $schemas;
} );

Two details are easy to miss. Mark deleted posts with creativeWorkStatus: Deleted rather than dropping them, or the reply tree stops making sense. And give each member a profile page marked up as ProfilePage, so author.url leads somewhere Google can read.

Common questions

Can I add DiscussionForumPosting to blog posts with comments?

No. Google says not to use it for articles or blog posts written by the site, even when readers comment on them.

Is JSON-LD allowed for forum markup?

Yes. Google recommends microdata for forums to avoid repeating long text, but JSON-LD is fully supported.

Do I need interaction counts?

No, they are recommended. Include them only when the forum really tracks and shows likes, views or replies.

How should I mark a post that a moderator removed?

Keep it in the markup if it still appears for context, and set creativeWorkStatus to Deleted.