WP Manifestindependent plugin directory
manifest / forms / gravityforms-response-management

Gravity Forms Response Management

Utility functions to manage and aggregate form entries for groups of respondents and forms.

★ 0stars

Install

Download source zip No release zip yet

This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/hughc/gravityforms-response-management/archive/refs/heads/master.zip
No built-in updater. New versions won't appear under Dashboard → Updates. Install new releases yourself, or let Git Updater track the repository.

Aggregate, browse and export Gravity Forms entries as a single workshop/survey dataset.

Gravity Forms is oriented towards anonymous collection — contact forms, questionnaires — and exports one form at a time. On a workshop or survey site the model is different: a user moves through a sequence of screens, answers several forms along the way, and those answers together constitute one response. This plugin treats a set of forms as one dataset and a set of respondents as one cohort.

Each output row is one known respondent's answers across all forms in a group; each column is a field from one of those forms. Respondents are identified by WordPress user ID — anonymous submissions are not handled.

Requirements

Component Requirement
WordPress 6+ (uses parse_blocks())
Gravity Forms Required — all entry access goes through GFAPI, tested against 3.0
Groups plugin Optional — enables Groups-backed respondent cohorts

No custom database tables. All configuration lives in two WordPress options.

Installation

Drop the folder into wp-content/plugins/ and activate. Nothing to configure on activation.

Usage

The UI is a single tabbed screen at Forms → Response Management. Every tab, AJAX endpoint and export requires the manage_options capability — this is an admin-only tool.

Setup

Define the two axes of a dataset:

Form groups — the forms that make up one dataset.

  • Manual selection: pick forms from a list.
  • Pattern: point at a parent page and the plugin discovers every gravityforms/form block in its child pages. Blocks are parsed recursively, so forms nested inside wrapper blocks (page builders, the Show Response wrapper) are found, and [gravityforms id=N] shortcodes are picked up as a fallback. Child pages are read in menu_order, which fixes the linear screen sequence and therefore the order of columns in the export.

Respondent groups — the cohort of users.

  • Manual selection: pick users; the ID list is stored as saved.
  • Groups plugin: pick a Groups group; membership is resolved fresh on every read, so later joins and leaves are picked up automatically.

Browse Responses

Pick a form group and a respondent group, then navigate respondent by respondent with < prev | (x/y) | next >.

  • Simple mode — choose one form; each step shows that user's complete submission to it.
  • Advanced mode — tick individual fields from any form in the group; each step shows just those fields, so you can compare one question across a cohort or skim a shortlist of answers across several forms.

Export Responses

Choose a form group, a respondent scope, and download a CSV.

Scope Rows exported
A respondent group Members of that group
All users Every logged-in user who has submitted to the selected form group

"All users" is a built-in scope, not a group you create — no Setup entry needed, and it works even with zero respondent groups defined. It resolves respondents from the entry table itself (DISTINCT created_by, scoped to the group's forms), so it means everyone who actually responded, not every WordPress user, and it picks up participants who were never assigned to a group. Anonymous submissions are excluded.

Entry status is not filtered — entries in any state, including trashed, are read.

Utilities

  • Clear user responses — delete every entry created by a user, across all forms or a selected subset.
  • Clear form responses — delete all entries for one form, in batches of 100.

Both delete permanently; there is no undo.

CSV layout

Row Contents
1 Form title, repeated across that form's columns (User over the first column)
2 Field label — the column header (user_login value sits under the first column)
3 … One row per respondent

Per respondent and per form, the most recent entry wins — the same rule as browse and aggregation, so repeated submissions don't duplicate rows. Checkbox and multi-select values are comma-joined, and field values are rendered through Gravity Forms' export logic, so Likert scales and custom field types resolve to readable text rather than stored IDs. A UTF-8 BOM is written for Excel.

Downloads are named responses-<form-group>-<respondent-scope>-<YYYY-MM-DD>.csv, e.g. responses-vacypa-all-users-2026-08-28.csv.

Data storage

Option Holds
gfrm_form_groups Form groups: name, type, resolved form_ids, parent page ID
gfrm_respondent_groups Respondent groups: name, type, user_ids, Groups group ID

Serialized arrays keyed by fg_<uniqid> / rg_<uniqid>. The all respondent scope is not stored here — it is a pseudo group, resolved at export time.

Architecture

Flat, static-only classes, no inheritance:

gravityforms-response-management.php   Bootstrap, admin menu, export handler, 4 AJAX endpoints
includes/class-form-groups.php         Form group CRUD + pattern discovery
includes/class-respondent-groups.php   Respondent group CRUD + Groups sync
includes/class-response-aggregator.php Aggregation, browse, CSV generation
includes/class-utils.php               Clear user / form responses
admin/class-admin-page.php             4-tab admin screen
admin/js/admin.js                      Toggles, field loading, browse navigation

Full design notes, decisions and known trade-offs: docs/implementation.md. Original requirements: docs/spec.md.

Notes and limitations

  • Destructive utilities delete entries outright, rather than blanking their field values.
  • Browse loads every respondent's entries for the selected scope, so very large cohorts are worth exporting instead of browsing.
  • A saved form group's form list is a snapshot of the pattern at save time; re-save to pick up forms added to the page tree afterwards.
  • Only respondents with a live WordPress user account appear in an export — entries belonging to a deleted account are skipped, though they stay in the database.