Show WordPress content only to logged-in users without a membership plugin

Published Updated 3 min read

A visitor sees a download button that only makes sense with an account. A phone shows a prompt to install a desktop app. A subscriber should see bonus content that guests do not. Three problems with one shape: show this to this kind of visitor and nobody else.

The usual advice is a membership plugin or a visibility add-on: Restrict Content Pro, MemberPress, Conditional Blocks. They handle access control, subscriptions and payment gates, and if you need content behind a paid tier or a signup flow, that is the category to look in. To show one paragraph to logged-in users and another to guests, they bring a lot of machinery to a small job.

WordPress already has the conditionals: is_user_logged_in(), wp_is_mobile() and current_user_can() cover the common cases. What is missing is a shortcode wrapper that works in Elementor, the classic editor or a text widget, with no admin screen and no licence key.

Block-editor controls and membership suites

Conditional Blocks adds visibility controls to the block sidebar, so a heading or group block can be hidden by login status, role or device. For a site built entirely in the block editor it is a clean answer. For a site whose layout lives in Elementor or the classic editor, it does nothing.

Restrict Content Pro, MemberPress and Members are built for access control at page and post level, with role management, gating shortcodes and, in paid versions, payments. Their free shortcodes are a side feature, and their admin footprint is sized for the whole job.

Two shortcodes and nothing else fit better: no settings, no role management screens, no upsell, nothing enqueued on the front end and nothing added to wp-admin. The conditionals themselves come from WordPress core and are well tested.

What the two shortcodes do

[show_if] outputs what it wraps only when its conditions are met; [hide_if] outputs it only when they are not. Both take the same three attributes.

login takes yes or no and uses is_user_logged_in(). device takes mobile or desktop and uses WordPress's own wp_is_mobile(). role takes a comma-separated list of role slugs and matches when the user holds at least one.

With several attributes on one tag, all must be true: [show_if login=yes device=mobile] shows only to logged-in visitors on a phone or tablet. Shortcodes nest inside either tag, because both run do_shortcode on their content before returning it.

  • [show_if login=yes]: logged-in users only
  • [show_if login=no]: guests only
  • [show_if device=mobile]: phones and tablets only
  • [show_if device=desktop]: desktop only
  • [show_if role=subscriber]: users with the subscriber role
  • [hide_if device=mobile]: everywhere except phones and tablets

Bonus content, desktop-only buttons, role notices

Put a PDF, a video or extended notes at the end of a post inside [show_if login=yes], with a [show_if login=no] block beside it carrying a message and a link to registration. Members get the bonus, guests get a reason to sign up, and there is no membership plugin, subscription or payment flow involved.

A download button for a Windows or Mac app, a browser extension, or anything that needs a big screen is pointless on a phone. Wrap it in [show_if device=desktop] and it is not in the mobile page at all. The content is never sent: not hidden with CSS, so nobody can reveal it by toggling display properties or reading the source.

Editor reminders to fill in SEO fields, admin warnings about a pending update, contributor prompts to submit a post: wrap them in [show_if role=editor] or [show_if role=administrator] and only the right people see them.

Content blocks, not pages

It controls inline blocks, not pages or post types. A logged-out visitor can still open a page whose content is all wrapped in [show_if login=yes]; they just see an empty page. Whole-page access control belongs to a membership or access plugin that hooks template_redirect and sends unauthorised visitors elsewhere.

There is no fallback message attribute. Pair a tag with its inverse, as in [show_if login=yes]The bonus content.[/show_if][show_if login=no]Log in to see this.[/show_if], so the fallback stays in your hands and can hold whatever HTML or shortcode your theme needs.

wp_is_mobile() reads the User-Agent header, the same check WordPress core uses, so it reliably separates phones and tablets from desktop browsers. It knows nothing about operating systems, browsers or screen widths. For layout breakpoints, use a media query; this is for functional differences.

What you get

Included

  • [show_if] shortcode that outputs content only when login status, device type, or user role conditions match
  • [hide_if] shortcode that suppresses content when conditions match, showing it to everyone else
  • Multiple conditions on one tag: all must be true for the content to appear
  • PHP-only output: hidden content is never sent to the browser, not hidden by CSS
  • Works in Elementor shortcode widgets, classic editor, Gutenberg shortcode blocks, and text widgets

Not included

  • Full-page or post-type access control that redirects unauthorised visitors
  • Subscription plans, payment gates, or any content unlocking workflow
  • Email gating or lead capture before showing content
  • Browser, operating system, or screen-width conditions beyond mobile versus desktop
  • A fallback message attribute - use a second shortcode with the inverse condition instead

Conditional Blocks does the things on the right. This build covers the part most sites use.

Questions

Will this work inside Elementor pages?

Yes. Add a Shortcode widget to the layout and put the shortcode in it. Elementor processes shortcodes in that widget, so the conditions apply as normal.

Build it in Steem

The button opens the builder with this guide's prompt filled in, so you can change anything before it runs. Nothing is built, and nothing is charged, until you send it.

Build this pluginAbout 55 credits. The free plan includes enough for one.
Read the prompt (240 words)

Build a WordPress plugin called Conditional Content Shortcodes. Plugin Name: Conditional Content Shortcodes. Description: Show or hide content blocks by login status, user role, or device type. Single PHP file. Register a shortcode [show_if] with three optional string attributes: login (accepts yes or no), device (accepts mobile or desktop), role (a comma-separated list of WordPress role slugs). Sanitize all three attribute values with sanitize_text_field before using them. Logic for [show_if]: if no attributes are provided, return do_shortcode applied to the enclosed content. If one or more attributes are provided, evaluate each one present. For login: yes requires is_user_logged_in() to be true; no requires it to be false. For device: mobile requires wp_is_mobile() to be true; desktop requires it to be false. For role: split the value on commas, trim whitespace from each slug, get the current user with wp_get_current_user(), and check whether the user roles array contains at least one of the slugs using in_array. If ALL evaluated conditions pass, return do_shortcode applied to the enclosed content. If any condition fails, return an empty string. Register a second shortcode [hide_if] with the same attributes and the same condition logic but inverted: if ALL conditions pass return an empty string, otherwise return do_shortcode applied to the enclosed content. If no attributes are provided, return do_shortcode applied to the content unchanged. No settings page, no admin menu, no styles, no scripts. The plugin has no side effects beyond registering the two shortcodes.