How to Show Related Content on Posts and Custom Post Types

a related-content feature needs two separate checks: where the block is allowed to appear, and which records it is allowed to link to.

Why it happens

WordPress is_single() already supports custom post types as well as posts. Use is_singular() with a post-type list when you want an explicit allowlist; it also supports pages and attachments when those types are requested.

if ( is_singular( array( 'post', 'game' ) ) ) {
    // Render related content.
}

This controls the current page. It does not control the publication status of the related items returned by a separate query.

Use two layers of filtering

  1. Limit the display context. Use is_singular() with an explicit list of supported post types.

  2. Limit related targets. Require the related-item query to return only published records.

  3. Generate links normally. Use WordPress permalink functions after the record has passed the status check.

  4. Test every supported post type. Check a normal post and each custom post type separately.

For a direct database query, the important condition is equivalent to:

AND posts.post_status = 'publish'

When using WP_Query, express the same rule with post_status => 'publish'.

Why both checks matter

The singular-page check answers, “Should this block appear here?” The status filter answers, “Is this related destination public?” They solve different problems.

A feature can correctly appear on a custom post type and still expose an unwanted draft link if the related query does not filter by status. The reverse is also possible: the query may return only published records, but the block may never appear because the page condition is too narrow.

Common mistakes

  • Cause: an overly broad display condition. Fix: use an explicit post-type allowlist rather than assuming is_single() excludes custom types.
  • Cause: relying on the current page status to protect related results. Fix: filter the related query itself to publish.

  • Cause: rendering stored HTML without inspecting its links. Fix: validate or regenerate saved related-content markup separately.

Exclude the current record and escape output

A related-content query should also exclude the current post, limit its result count, and specify the intended destination post types. Use esc_url() for the permalink and esc_html() for the link label. Test as a logged-out visitor so editor permissions do not conceal a public-status mistake.

Make the display rule explicit, then independently enforce public status in the related-item query. The next action is to test the feature on one standard post, one custom post, and one draft related record.

Reference: WordPress is_single reference.

Leave a Reply