How to show users only their own Gravity Forms entries
A complete walkthrough for filtering a Gravity Tables view so each logged-in user sees only the entries they submitted, with role permissions and edge-case handling.
If you’re building a customer portal, an internal HR view, or a team dashboard, “let each user see only their own entries” is almost always the first requirement. This guide walks through the complete pattern.
TL;DR#
Add filter_by_user="true" to your shortcode:
[gravity_table id="42" filter_by_user="true"]
That’s the one-line answer. Read on for the edge cases that come up the moment a real user hits the page.
How it works internally#
Every Gravity Forms entry has a created_by field that stores the WordPress user ID of whoever submitted it (or 0 for guest submissions). When filter_by_user="true" is set:
- Gravity Tables reads
wp_get_current_user()->ID - Adds a
WHERE created_by = Xclause to the entry query at the database layer - Renders only matching entries
- Enforces this server-side, even if someone modifies the DOM, the data hasn’t been sent
The filter is applied before any other table filter, sort, or search runs. The user can’t escape the visibility gate by clicking around.
What about logged-out users?#
By default, a logged-out user sees an empty table with a polite “log in to see your submissions” message. To change the message:
[gravity_table id="42" filter_by_user="true" guest_message="Sign in to view your orders."]
To hide the table entirely from logged-out users:
[gravity_table id="42" filter_by_user="true" require_login="true"]
With require_login="true", the table renders nothing for guests, useful when the table itself is sensitive (e.g., a billing dashboard you don’t want signaling its existence).
Combining with role permissions#
filter_by_user="true" is per-user filtering, each logged-in user sees their own. If you also want to gate the entire table to specific roles:
[gravity_table id="42" filter_by_user="true" allowed_roles="customer,subscriber"]
Now:
- Guests: see the guest message
- Logged-in
customer/subscriber: see their own entries - Logged-in admin: sees… wait, they’re not in the allowed list, so they see nothing
That last case bites people. By default, admins are not auto-included in allowed_roles, that’s a feature, since it lets you build dashboards an admin shouldn’t see by default. To always allow admins:
[gravity_table id="42" filter_by_user="true" allowed_roles="customer,administrator"]
Or use the special token * to allow any logged-in user:
[gravity_table id="42" filter_by_user="true" allowed_roles="*"]
Letting admins see everything (and switch users)#
For staff dashboards where a customer-service rep needs to view a customer’s entries, there’s a separate parameter:
[gravity_table id="42" filter_by_user="true" allow_user_switch="manage_options"]
The allow_user_switch="manage_options" lets any user with the manage_options capability (admins by default) override the filter from the table toolbar, a small “Viewing as: customer@example.com” dropdown appears.
Without this, admins are subject to the same created_by filter as everyone else.
Inline editing + per-user filter#
If you also enable inline editing on a per-user table:
[gravity_table id="42" filter_by_user="true" allow_edit="phone,address,preferences"]
The user can edit only their own rows because the row-level permission check ANDs with the per-user filter. They literally don’t see anyone else’s rows, so editing them isn’t a question.
If a malicious user tampers with the DOM to inject a different entry ID into the edit AJAX call, the server-side handler re-runs the per-user check and returns a 403. There’s no client-side trust here.
Edge cases worth knowing#
Entries created via the GF admin#
Entries submitted through /wp-admin/admin.php?page=gf_entries are created by the admin doing the submission. Their created_by is set to that admin’s user ID, not the customer’s.
If your workflow involves admins entering data on behalf of customers, you have three options:
- Don’t, have customers submit through the front-end form
- Add a “Submitted on behalf of” field that links to the customer’s user ID, and use Gravity Tables’
lookup_fieldinstead ofcreated_by - Run a one-time migration that rewrites
created_bybased on the submitted-on-behalf-of field
Option 2 is what most teams settle on.
Entries from the REST API#
Programmatic entries created via Gravity Forms’ REST API typically have created_by = 0 unless the API call is authenticated as a specific user. If you’re integrating Zapier, Make, or a custom script, double-check this, entries that are nobody’s will be invisible to everyone in a per-user filter.
Entries imported from CSV#
CSV imports (via the GF Import/Export plugin) default to created_by of the importing admin. Same caveat as the admin-submitted case.
Quick recipes#
Customer order portal:
[gravity_table id="orders" filter_by_user="true" allow_edit="shipping_address" export="csv,pdf"]
Internal HR view (employee sees own profile):
[gravity_table id="employee-profile" filter_by_user="true" allow_edit="phone,emergency_contact"]
Team task list (each member sees own):
[gravity_table id="tasks" filter_by_user="true" filters="status,priority" allow_edit="status"]
What this replaces#
Without per-user filtering, every team that wants this pattern ends up:
- Building a custom WordPress page template that calls
GFAPI::get_entries()with manualcreated_byfiltering - Wrapping that in role checks that have to be maintained separately
- Forgetting to gate the export endpoint and discovering CSV exposure six months later
filter_by_user="true" is one parameter that handles all three of those, audited and battle-tested across hundreds of production sites.