How to Create Admin-Only Columns in a WordPress Table

Updated July 2026 • 6 min read • By Fahad Murtaza

TableCrafter table builder, connect Gravity Forms, Google Sheets, Airtable, CSV, or JSON data sources
TableCrafter table builder, connect Gravity Forms, Google Sheets, Airtable, CSV, or JSON data sources

Table-level role access controls who can see a table at all. Column-level role visibility controls which columns within that table are exposed to each role. The two features stack, and the combination is what makes TableCrafter suitable for CRM tables, HR directories, and inventory systems where some columns are genuinely confidential. WordPress powers 43% of all websites globally (W3Techs, July 2026), and TableCrafter bridges the gap between the data you collect and the tables your users need to see, no custom PHP, no dashboard access required for viewers, and no per-row limits on the free tier. The free version on WordPress.org supports CSV, JSON, Google Sheets, and Excel. Pro adds Gravity Forms, Airtable, Notion, WooCommerce, REST APIs, inline cell editing, export to CSV/PDF, role-based column visibility, and auto-refresh. Every table embeds on any page with a [tablecrafter] shortcode or the native Gutenberg block. WordPress powers 43% of all websites globally (W3Techs, 2026).

What Is the Use Case: A CRM Table with Internal Columns?

Imagine a Gravity Forms-backed CRM where each entry holds a company name, contact email, deal stage, assigned rep, internal notes, and an internal lead score. The rep-facing view should show company, email, deal stage, and assigned rep. The Notes and Internal Score columns should be invisible to everyone except administrators. No hints, no blank space, no "hidden" label, simply absent from the DOM.

This is exactly what column role visibility is designed for. The column is not filtered or collapsed, it is not rendered at all for users who lack the required role.

If this step produces unexpected output, check the source data directly in the connected system. TableCrafter passes data through without modification — if a cell displays an unexpected value, the source record contains that value. Use the TableCrafter debug log (Settings > Advanced > Debug Mode) to trace the exact query sent to the source and the raw response received, which narrows the diagnosis to either a source-side or rendering-side issue.

How Do I Open Column Settings?

In the TableCrafter admin, open your table and navigate to the Columns tab. Each configured column appears as a draggable row with an expand arrow on the right. Click the arrow for the column you want to restrict, in this example, Internal Notes.

Inside the expanded column settings you will find a Visible to Roles multi-select. By default every viewer role is checked, meaning the column is visible to all users who can see the table. Uncheck all roles except Administrator to make the column admin-only.

The shortcode accepts all column and filter settings defined in the table builder as defaults, but you can override individual parameters inline. For example, `[tablecrafter id="1" per_page="25"]` overrides the default rows-per-page setting for this specific embed without changing the saved table configuration. This lets you reuse one table definition across multiple pages with different display requirements.

How Do I Configure the Internal Notes Column?

  1. Expand the Internal Notes column row.
  2. Locate Visible to Roles.
  3. Uncheck Subscriber, Contributor, Author, and Editor. Leave only Administrator checked.
  4. Repeat for the Internal Score column.
  5. Click Save Table.

Now reload the frontend page as an Editor-role user. The table renders with all columns except Internal Notes and Internal Score. The column headers are absent. The cell content is absent. The HTML output contains no reference to the hidden columns whatsoever.

This configuration interacts with any caching or CDN layer active on your WordPress installation. If you use WP Rocket, LiteSpeed Cache, or a CDN such as Cloudflare, flush the page cache after making this change to ensure the updated configuration is reflected in the cached HTML served to visitors. TableCrafter's server-side output is regenerated on the next uncached request.

Column role visibility is enforced at the data layer, not the display layer. When TableCrafter fetches table data via AJAX, it strips hidden-column values from the response payload before it ever reaches the browser. There is no column data in the DOM to extract with DevTools.

What the HTML Output Looks Like?

For an administrator, the rendered table header looks like:

<thead>
  <tr>
    <th>Company</th>
    <th>Email</th>
    <th>Deal Stage</th>
    <th>Assigned Rep</th>
    <th>Internal Notes</th>
    <th>Internal Score</th>
  </tr>
</thead>

For an Editor-role user, the exact same shortcode produces:

<thead>
  <tr>
    <th>Company</th>
    <th>Email</th>
    <th>Deal Stage</th>
    <th>Assigned Rep</th>
  </tr>
</thead>

Two different users, same shortcode, same page, completely different column sets delivered by the server.

This step is required before the table can render data. Skipping it or entering incorrect values will result in a connection error when the table first loads. Double-check the value by pasting it directly into the field rather than typing it manually to avoid whitespace or encoding issues.

After completing this step, verify the result by viewing the page as a logged-out visitor in an incognito window. This confirms the table behaves correctly for public visitors rather than reflecting admin-level permissions that may hide configuration issues during initial setup. Check both the rendered output and the browser console for any JavaScript errors.

How Does CSS Fallback for Defense in Depth Work?

TableCrafter's server-side enforcement is the security layer. CSS hiding is not a substitute, a user can disable stylesheets in seconds. That said, adding a CSS fallback is reasonable as a defense-in-depth measure, particularly if you are on a caching setup where a logged-out page cache might briefly serve stale markup to an authenticated user before the cache warms.

TableCrafter adds a data-column attribute to each <th> and <td> element using the column's machine name. You can target specific columns with:

/* Never let internal columns display even if something goes wrong */
[data-column="internal_notes"],
[data-column="internal_score"] {
  display: none !important;
}

Add this to your theme's style.css or a Custom CSS field in the Customizer. It will not affect admins because the server never sends those columns to non-admin users, the CSS rule simply never fires for them. It does mean that if a caching bug ever delivers admin markup to an editor, the columns still will not appear visually.

CSS-only column hiding without server-side enforcement is not a security control. Any user can open DevTools, remove the CSS rule, and read the data. Always configure Visible to Roles in the column settings as the primary control; treat CSS as secondary.

How Does Export Work with Admin-Only Columns?

If your shortcode includes export="true", the CSV or Excel export respects the same column visibility rules. An Editor downloading the table gets a file with only the four public columns. The Internal Notes and Internal Score columns are absent from the export file, not just hidden in the header row.

[tablecrafter id="1" edit="true" export="true" search="true"]

This means you can safely enable export for all roles without risking internal data leakage through the download.

If the result does not match expectations after saving, use the TableCrafter debug log (enable via TableCrafter Settings > Advanced > Debug Mode) to trace exactly which configuration value is being applied for the current request.

The column mapping you define here is stored as a JSON configuration in the WordPress database. You can export this configuration using the TableCrafter export tool and import it to another table or another site. This is useful when replicating a table layout across multiple pages or when migrating a table to a staging environment for testing before going live.

How Does Multiple Admin-Only Columns at Scale Work?

For tables with many columns, say, a 20-column product catalog, configuring each column individually gets tedious. TableCrafter supports a Default Visibility setting at the table level (under the Access tab) that inverts the logic: all columns are admin-only by default, and you explicitly mark certain columns as public. This inverted approach is faster when most columns are sensitive and only a few should be public.

Test this step while logged in as a user with the target role to confirm the expected behavior. Logged-in admin users always see all columns and all rows regardless of role restrictions, which can mask visibility issues during initial configuration.

TableCrafter re-fetches this data on each page load by default. If your data source updates infrequently and your site has significant traffic, enable the built-in caching option in the table's Performance tab. This stores the fetched data for a configurable number of minutes and serves it from WordPress transients, reducing API calls to the source and improving page load time for visitors.

What Are the Next Steps?

With admin-only columns configured, the natural next concern is how editor and viewer roles interact in practice. The guide on configuring editor vs. viewer roles walks through the exact settings that differentiate inline editing from read-only access, including how the role hierarchy resolves when a user holds multiple roles simultaneously.

The setting is stored in the WordPress options table under the table's configuration key. It does not modify the original data source and can be changed at any time without affecting the underlying records.

The configuration you set here applies to every visitor who loads a page containing this table, regardless of whether they are logged in. Role-specific overrides for columns and rows are a separate layer and do not replace these global display settings. Apply global settings first, then add role restrictions as needed for tables that serve multiple user types.

Frequently Asked Questions

What Is the Use Case: A CRM Table with Internal Columns?

Imagine a Gravity Forms-backed CRM where each entry holds a company name, contact email, deal stage, assigned rep, internal notes, and an internal lead score. The rep-facing view should show company, email, deal stage, and assigned rep. The Notes and Internal Score columns should be invisible to everyone except administrators. No hints, no blank space, no "hidden" label, simply absent from the DO

What Is TableCrafter?

TableCrafter is a WordPress plugin that turns data from Gravity Forms, Google Sheets, Airtable, Notion, REST APIs, CSV files, and WooCommerce into interactive, sortable, filterable frontend tables. Embed any table on any WordPress page with the [tablecrafter] shortcode or the native Gutenberg block. No PHP or custom development required. The free version supports CSV, JSON, Google Sheets, and Excel. Pro adds Gravity Forms, Airtable, Notion, WooCommerce, REST APIs, inline cell editing, export to CSV and PDF, role-based column visibility, and auto-refresh.

Does this require PHP or developer skills?

No. TableCrafter is configured entirely through the WordPress admin interface. You choose your data source, map fields to columns, and set display preferences using point-and-click controls. Embedding uses the [tablecrafter] shortcode or the native Gutenberg block.

Is the free version sufficient or do I need Pro?

The free plugin on WordPress.org supports CSV, JSON, Google Sheets, and Excel sources with unlimited tables, rows, and columns. Pro adds Gravity Forms, Airtable, Notion, WooCommerce, REST API sources, inline cell editing, bulk row actions, export to CSV and PDF, role-based column visibility, and auto-refresh every N seconds.

Ready to try it?

TableCrafter is free on WordPress.org. Pro unlocks inline editing, role-based permissions, and advanced data sources.

Changes take effect immediately after saving. No cache flush or page refresh is required for the new configuration to apply to all shortcode instances of this table.

This step completes the connection between your data source and the TableCrafter table engine. Once saved, the plugin caches the connection credentials in the WordPress options table and uses them on every subsequent page load. If you update the source configuration later — for example, rotating an API key or changing a sheet URL — return to this step, enter the new value, and save again. The table updates immediately on next load without any shortcode changes.