Start with a saved report.
Build one visually, ask AI for a draft, or schedule a report you have already saved. The plugin is in private beta; request access here.
wp-admin → Report Studio → New. Name it, pick what to report on, and tick the details you want from Popular details or All details. It saves as you go; click View report when it looks right.
Click Describe with AI and type what you want. Check the columns and filters it proposes and adjust them. The report saves as you go.
Open a saved report → Schedule. Pick day + time. Add recipients. Pick CSV or XLSX. Save.

Reports, columns and filters.
These terms appear in the builder and report viewer.
Report
A saved set of columns, filters and sort for one root post type. Reports are stored as their own post type (vrb_report), so your normal site backups include them. Five plugin capabilities control who can view, build, export, bulk-edit or schedule them; see Roles & capabilities.
Root post type
What each row represents. For one row per product, pick product; for one row per project, pick project. Columns can pull data from related posts, but every row belongs to one root post. (Repeater columns are the exception that adds rows: one per repeater item.)
Column
One value per row. Columns are built from paths: a sequence of steps from the root post to the final field. A simple path is one step (post_title on the root). A complex path traverses repeaters and relationships (project › Travel Arrangements (repeater) › Travel Arrangement (relationship) › Airline (meta)).
Filter
A condition that narrows which root posts appear. Filters use the same paths as columns, so you can filter on any field you could show, whether or not it's a column. Multiple filters combine with ALL (AND) or ANY (OR).
project.client.name and project.lead.name both end at a name meta key, but on different posts. The path records which route the column takes.
The Builder, top to bottom.
The Builder is a single screen. Work through it top to bottom, and go back to any part whenever you like.

1. Pick a starting post type
The dropdown lists every post type the current user can read, each with its post count.
WordPress's internal types (revisions, menu items, customizer changesets and similar) and plugin configuration types such as ACF field groups are left out. Add or remove types with the vrb_reportable_post_types filter if your install needs them.
2. Add columns and filters
Click Choose details to open the picker beside the report. It opens on Popular details: the fields filled in on most of your records, with an example value from your newest ones. Tick a field to add it as a column; the table updates as you go. All details lists everything, one place at a time, and the search box finds a field by its name, by the place it sits in, or by a value you recognise.
All details covers:
- Post fields: title, status, date, author, slug.
- Taxonomies: categories, tags and any custom taxonomy registered for the type.
- ACF, Meta Box and Pods fields, including groups, repeaters and relationships, which expand to show their sub-fields. See Repeaters and relationships.
- Other postmeta: meta keys used by posts of this type, with the data type (number, date, text) inferred from sample values. Keys that don't belong to a registered field are listed under "Extra saved data".
- Computed fields: values that aren't stored as postmeta. With WP Statistics or Independent Analytics installed you get a "Page views" column. Developers can add their own through
vrb_virtual_providers(see the developer guide).
Filter filters rows on any field, shown or not. Each column header has a ⋯ menu to sort, rename, filter by it, move or remove it, and headers can be dragged to reorder.
A field's Details say where it's stored and how often it's filled in. Fields you never use can be hidden from the picker, just for you or for everyone (administrators only). Hidden fields stay in any report that uses them and are listed under All details › Hidden fields.
3. Filters in depth
A filter is a field, a condition and a value. The conditions offered depend on the field's data type:
| Field type | Conditions |
|---|---|
| Text, choice, taxonomy | is one of · is not one of · contains · does not contain · starts with · ends with · is empty · is not empty |
| Number | is · is not · > · ≥ · < · ≤ · is one of · is not one of · is empty · is not empty |
| Date | year is · is between · is before · is on or before · is after · is on or after · is on · is not on · is empty · is not empty |
"Is one of" lets you tick several values. "Year is" covers whole calendar years: choose 2025 and 2026 to include every date in both. Date comparisons work with ACF's stored date format as well as standard dates.
4. Combine filters with ANY or ALL
With two or more filters, a Match toggle appears above them:
- ALL (AND): a post must meet every filter. This is the default.
- ANY (OR): a post appears if it meets at least one.
Several values for the same field (added from a value search, for example) are grouped in a "Match any of these values" box, so status is Active or Pending, and region is North works under ALL. Nested AND/OR groups beyond that aren't supported yet.
5. Sort, preview and saving
Add one or more sort columns; the first one is the main order. The report and its exports use the saved sort. Clicking a column header in the report view re-sorts for that visit only. The builder's table is a live preview of the first 10 rows (Show 50 for more). View report opens the full report.
There is no Save button: the builder saves as you go, and the line under the report's name says whether everything is saved. If a save fails it keeps retrying and offers Try now; Cmd/Ctrl+S saves at once. A saved report's URL can be shared with colleagues; opening it still requires the right capability.
Report on repeaters and related posts.
Custom data is often spread across groups, repeaters and linked posts. Report Studio can follow those links, so a column can show a value from a related post. Groups work in Free; repeaters and relationships are Pro.
Groups
An ACF group only organises fields, so its sub-fields behave like any other field. A group named projected_profit with fields revenue_subtotal and expenses_subtotal appears as an expandable item, and the column reads wp_postmeta at projected_profit_revenue_subtotal from postmeta.
Repeaters
A repeater holds a list of entries per post, such as a project's travel arrangements. Ticking it adds one cell with a line per entry, so each post stays one row; Choose … details under it sets what each line shows. To give each entry its own row instead, open Layout and choose one row per entry: a project with three travel arrangements then gives three rows. The Layout menu also decides whether posts with no entries are included. A repeater filter can restrict which entries appear.
Up to 50 items per post are expanded by default. A developer can raise this with the vrb_repeater_max_size filter, so check your largest repeaters before relying on the totals.
Relationships
A relationship field (ACF Relationship or Post Object, Meta Box post fields, Pods relationships) points to other posts. Open it in the picker to see the linked post type's fields. Add one, and the column shows that value from the linked post.
Example: a project has a client relationship pointing at the company post type. Add the company's phone field and each project row shows its client's phone number.
Combining them
You can combine supported repeater and relationship steps. For example:
project
› Travel Arrangements (repeater)
› Travel Arrangement (relationship → travel-arrangement)
› Linked Crew Member (relationship → crew-member)
› Contact Name First Name (meta) Four steps across three post types, shown as one "First Name" column with a value for each repeater entry.
Draft reports with your own AI provider.
AI is optional. With a provider connected, you can describe a report in the Builder, or ask for report ideas on the Suggestions page. Everything else works without it.
The Builder bar
Click Describe with AI at the top of the Builder. Type something like "published posts from last month, newest first" and click Generate. The model's draft (post type, columns, filters and sort) fills the Builder. Check it and fix anything that's wrong; it saves as you go.
The request includes a summary of your site's structure: post types, custom fields, taxonomies, and up to eight sample values from each of up to six short text or choice fields. The samples help the model pick filter values that exist on your site. Post content, long text, URLs and email fields are not sampled.
AI Suggestions
On Report Studio → AI suggestions, click Suggest reports for my site →. The model looks at the same site summary plus your active plugins (WooCommerce, for example) and proposes five reports. Create a draft from any of them, then check its fields, filters and results.

Picking a provider (BYOK)
Requests go from your WordPress server straight to the provider you choose. We don't proxy them and never see your key or prompts. Pick a provider in Settings → AI:
- OpenRouter: the default. Its free models need an account but no card, with a daily request limit set by OpenRouter. With no model chosen, the plugin tries two recommended free models, then OpenRouter's free router. The easiest way to try AI.
- Google AI Studio: Gemini models, with a free tier whose limits Google sets.
- Anthropic: paid. Claude models were the most accurate in our testing on reports that follow repeaters and relationships.
- OpenAI: paid. Defaults to a low-cost model that returns the structured output the plugin needs.
- Ollama: runs models on hardware you control, so requests never leave your network. Use a large model (30B parameters or more); smaller ones often return output the plugin can't read.
For local Ollama, set VRB_ALLOW_LOOPBACK_AI to true in wp-config.php. By default the plugin refuses private and loopback addresses (127.x, 10.x, 172.16–31.x, 192.168.x, *.local, 169.254.x), so a stored endpoint can't be used to probe your internal network. The constant turns that check off.

When AI gets it wrong
Errors show the provider's reason. The common ones:
- Rate-limited: shows how long to wait. Wait, or switch provider.
- Model not available: pick another from Browse available models.
- Context too long: your site summary is too big for the model. Choose one with a larger context window.
- Could not parse suggestions: the model's reply wasn't valid JSON. This happens most with small local models; try a larger one.
Where reports live.
Opening a saved report runs it against current data and shows the result as a table you can sort, filter and page through.

Runtime filter chips
Each saved filter appears as a chip above the table. Click × to drop one for this visit; the saved report doesn't change. Click + to add a temporary filter. Exports use whatever filters are showing.
Excel-style column filters
Click any column header. The menu has Sort ascending / descending, Filter by values…, Custom filter…, and Hide column. "Filter by values" lists the column's distinct values (up to 200) with checkboxes. Tick the ones you want and the table updates.
The value list is cached for five minutes, so reopening the menu is quick.

Pagination + page size
Choose 25, 50, 100 or 200 rows per page. Page counts reflect the active filters. The page size and sort are kept in the URL, so a shared link opens the same view.
Export and email reports.
Export any report when you need it, or email it on a schedule. Exports use the filters currently applied.
CSV (Free)
Click Download → CSV on a report. Exports include the current filters and sort. The default limit is 50,000 rows; larger results show an error rather than downloading a partial file. Narrow the filters, or ask your developer about the vrb_query_max_rows limit.
XLSX (Pro)
Download → XLSX creates an Excel workbook with numeric cells for number columns, so formulas and numeric sorts work. It includes bold headers and a frozen first row.
Include source post links
A toggle in the Export menu adds a "Source" column with each row's WordPress edit link. Google Sheets makes these clickable; Excel and Numbers show them as text.
Scheduled email (Pro)
In a saved report, open the Schedule panel and turn on "Email this report on a schedule". Choose daily or weekly, the day and time, the recipients (comma- or line-separated) and CSV or XLSX, then save. Send now sends a copy immediately so you can check delivery.
Mail goes through WordPress's wp_mail(), so your SMTP plugin handles it. WP-Cron checks for due schedules every five minutes. If cron stops running (a quiet site, or DISABLE_WP_CRON without a server cron job), Diagnostics shows when it last ran. A failed send is marked on the schedule with its reason; the next scheduled run tries again.

Change matching posts, with 30 days to undo.
Preview a change to selected posts or all matching posts before running it. Undo is available for 30 days. Posts edited after the action are skipped, and the result reports restored and skipped counts.
The flow
- In the report view, choose an action from the menu beside the page-size selector.
- Tick the rows to change (shift-click selects a range), or apply it to every matching post.
- Click Apply. A preview shows what will change, how many posts are affected and a before/after view of the first ten.
- Click Confirm and run, or Cancel.
- The job is listed in
Bulk actions → History, with Undo available for 30 days.
Built-in actions
- Move to Trash: Undo puts each post back with its original status (published, draft or private). WordPress's own Trash restore would make it a draft.
- Change status: publish, draft and so on. Each post's previous status is recorded.
- Update meta value: set one or more custom fields. Previous values are recorded, including fields that were empty, and Undo puts them back.
- Update field: change a post field such as the title, excerpt or slug, with the same Undo.
Large selections
Up to 100 posts run immediately. Larger jobs run in the background through Action Scheduler (when installed) or WP-Cron, 25 posts at a time, and the History page shows progress as they go. Every post is checked against the user's permissions; posts they can't edit are skipped and counted.
Custom actions
Not a supported API yet. The built-in actions use an internal registry whose snapshot and undo contract is still changing. You can already react to bulk jobs with the vrb_bulk_job_completed, _failed and _undone actions (see the developer guide). If you need a custom action, tell us what it should do.
Every field on the Settings page.

License
Shows whether the site is on Free or Pro. Manage license opens the Freemius customer portal, where you can change plan, move the license to another site or cancel.
AI Settings
- AI Provider: hosted providers and local Ollama. See AI features.
- API Key: stored encrypted (AES-256) in
wp_options. Requests go from your server to the provider; we never see the key or your prompts. - Custom Endpoint: your Ollama address, or a different OpenRouter URL. Leave blank for the provider's default.
- Model: leave blank for the default, or pick one from Browse available models (free models are tagged; paid ones show an estimated cost per request).
Roles & capabilities
Every screen and request checks one of five capabilities. By default, anyone with WordPress's edit_posts capability (Contributors and above) has all five. To tighten that, assign the capabilities per role with any role-editor plugin (User Role Editor, Members, PublishPress Capabilities). An explicit deny on a role wins even when the user still has edit_posts; administrators always keep all five.
| Capability | Grants |
|---|---|
vrb_view_reports | Reports list, search, opening and running a saved report |
vrb_edit_reports | New report, the Builder, save / duplicate / delete, AI, templates |
vrb_export_reports | CSV and XLSX downloads |
vrb_run_bulk_actions | Bulk actions, history and undo (Pro) |
vrb_manage_schedules | Schedule panel and Send now (Pro) |
Example: a read-only reporting role that can export. add_role( 'report_viewer', 'Report Viewer', [ 'read' => true, 'vrb_view_reports' => true, 'vrb_export_reports' => true ] ); To grant nothing by default and hand out capabilities explicitly, add add_filter( 'vrb_grant_caps_via_edit_posts', '__return_false' );.
Constants you can set in wp-config.php
| Constant | Effect |
|---|---|
VRB_ALLOW_LOOPBACK_AI | Allows AI calls to loopback / private-network addresses (Ollama on localhost, etc.). Default false. |
Hooks for developers
Extend Report Studio from your own plugin, theme or mu-plugin without touching its code. The developer guide has every hook with its arguments, the compatibility policy and an example extension you can download. The same guide ships in the plugin as DEVELOPERS.md. The most-used hooks:
| Lifecycle action (beta) | Fires when |
|---|---|
vrb_report_saved | A report was created or saved. |
vrb_report_ran | A saved report ran in the viewer (row count, timing). |
vrb_report_run_failed | A viewer run hit a database error or exception. |
vrb_export_completed | A CSV/XLSX download or scheduled attachment finished (row count). |
vrb_export_failed | An export couldn't be produced (e.g. over the row cap). |
vrb_schedule_sent | A scheduled report was emailed (Pro). |
vrb_schedule_failed | A scheduled delivery failed (Pro). |
vrb_bulk_job_completed / _failed / _undone | A bulk action finished, stopped early, or was undone (Pro). |
| Filter | Use it for |
|---|---|
vrb_virtual_providers | Add computed or external-table columns from your own SQL. |
vrb_field_sources | Integrate another custom-fields plugin. |
vrb_reportable_post_types | Add or remove post types offered as a report's root. |
vrb_query_post_statuses | Change which post statuses reports include. |
vrb_query_max_rows | Safety cap for exports and scheduled deliveries. Default 50,000. |
vrb_grant_caps_via_edit_posts | Return false so access comes only from the vrb_* capabilities. |
vrb_bulk_required_post_caps | Per-post capabilities a bulk action needs. |
vrb_export_source_column_label | Rename the edit-link column in CSV/XLSX exports. |
When something looks wrong.
Step one: copy the diagnostic bundle
Report Studio → Diagnostics → Copy diagnostic bundle copies one block of text: plugin, WordPress and PHP versions, theme, active plugins and the last 20 log entries. Paste it into your support email so we can start from your setup.

Common errors
Your site summary (post types, fields and sample values) is larger than the model's context window. Choose a model with a larger context window through Settings → AI → Browse available models.
The provider doesn't recognise the model ID: it was retired or mistyped. Pick a current one from Browse available models. On Ollama, check that Custom Endpoint has the host and port (for example http://localhost:11434); the plugin adds the API path itself.
Hosted providers get 120 seconds and Ollama gets 180. Suggestions for a site with many fields can take over a minute, so let it finish before retrying. If it times out every time, choose a faster model, or check that your server allows outbound HTTPS.
The model replied, but not with valid JSON. Small local models do this most often. Try again, or use a larger model.
First check the schedule itself: a failed send shows its reason there. Then open Diagnostics, which warns when WP-Cron hasn't run for more than 15 minutes. Usual causes: DISABLE_WP_CRON is set with no server cron job, the site gets too little traffic to trigger WP-Cron, or the SMTP plugin is misconfigured (send a test from that plugin to check).
Look under All details › Extra saved data in the picker, or check All details › Hidden fields in case someone hid it. Extra saved data is meta keys that don't belong to a registered ACF, Meta Box or Pods field, usually written by another plugin or left from an old field. They work as columns.
Reach us
support@wpreportstudio.com Include the diagnostic bundle, what you did and what you expected to happen.