Gravity Forms is evolving. Since the release of version 1.0 in August 2009 it quickly became the leading commercial form-building plugin for WordPress. Now, according to analysis by Datanyze, it’s being used on more sites in the Alexa top 1M than all the other form-builder tools in its list put together.
Comparisons like these, of course, can be a bit misleading, not least because there’s an important difference between Gravity Forms and the other technologies on their list. Gravity Forms is installed and runs entirely on the host server, whereas the others embed the form on the page in a relatively superficial way so the processing and storage has to be performed externally. This means that Gravity Forms can be customised, extended and integrated in ways the others can’t and perhaps this advantage puts it into a different category altogether.
With over one million WordPress sites running Gravity Forms, there’s already a sizeable install base and a healthy ecosystem is emerging of third-party developers providing high-quality add-ons, themes, mobile apps and custom line-of-business solutions. If the feature requests from customers are anything to go by there’s plenty of room for new ideas and growth.
In response to this dramatic growth, at Rocketgenius, the company behind Gravity Forms, we’ve been working very hard over the last couple of years to consolidate on this early success with a laser-like focus on stability, scalability and extensibility. The tools we’ve been building provide the common foundation for the development of all our 17+ add-ons and simplify their maintenance. Essentially what we’ve built is an application framework for WordPress and now we’re engaging with third-party developers and end-customer IT departments and helping them use Gravity Forms as a platform for their own projects.
Since the release of version 1.8, Gravity Forms now has the following tools as part of the developer platform:
- Actions and Filters
- A Framework for Add-On development
- API Functions which provide programmatic access to the Forms and Entries on the local Gravity Forms installation.
- Web API (and the Web API PHP Wrapper) providing secure remote access to Gravity Forms
In this introduction, I’ll be bringing together all these tools into a single tutorial - the development of an add-on – primarily to give a sense of what can be done and the best way to approach it. I’ll be assuming at least a little experience with Gravity Forms and reasonable familiarity with PHP. The inline comments in the code are intended to be read as part of the tutorial.
Some preliminary analysis
Let’s briefly run through the analysis phase and list some requirements for the add-on.
Use Case A
A marketing analyst in the head-office of a national organisation is responsible for analysing the all submissions of the same customer satisfaction survey installed on multiple regional sales sites. The analyst needs the aggregate results in real-time. However, the regional representatives only need access to the local entries and results on the site for which they are responsible.
Use Case B
A database Backup is scheduled nightly but there have been some availability issues recently with the backup service. Form submissions must be backed up to a server at a different location which is kept ready to be promoted should the production site fail.
Use Case C
The form submissions from a quiz evaluating patients’ mental health contain sensitive information and must not be collected on the public site – all information must be stored and analysed on an internal server which follows strict legal procedures and has a high level of security. The firewall is configured to allow the public site to communicate with the internal site.
Use Case D
The staging site data needs to be kept in sync with the production site.
Now we know what the solution should involve we can list some basic requirements for the add-on.
- Form submissions (entries) should be sent to a remote Gravity Forms installation for storage (aggregation)
- Aggregation will be activated by the local administrator on a form-by-form basis.
- Entries will be optionally deleted after sending to the remote site.
- If the form doesn’t exist on the remote site the add-on will create it.
- The add-on will allow the central site admin to activate a results page and the results page should allow results to be filtered by site
So we’ll need to extend Gravity Forms in the following steps:
- Create an add-on that uses the Add-On Framework
- Add a tab in the Gravity Forms Settings page to collect the API credentials for the remote site and activate the results page
- Add a Results Page
- Add a tab in the Form Settings with options to activate aggregation and delete entries.
- Add a custom Entry Meta field to the Entry Object and store a site identifier so the results page can filter the entries by site
- During Initialisation, hook into the appropriate action to execute our code after the form has been submitted
- Use the Web API to store the entry on the remote site
- Use the API Functions to delete the local entry
Step 1: Extending the Add-On Framework
The first thing we need to do is create an empty class for the add-on. We could of course create an independent class of our own but by using the Add-On Framework we get a big help with the following:
- Add-On Initialisation and executing code at the right points
- Enforcing a Gravity Forms minimum version requirement. Gravity Forms, in turn, enforces a minimum version requirement for WordPress.
- Creating settings pages (add-on and form settings) with a complete Settings API
- Granular, role-based, permissions and integration with the Members plugin
- Conditional script enqueuing including automatic support for the no-conflict mode in Gravity Forms which helps prevent conflicts with other plugins installed on the server
- Adding custom meta fields to the entry object
- Creating form feeds – A feed is a user-configurable action that gets conditionally processed after a form is submitted.
- Displaying charts and filtering results
- Integration with the Gravity Forms Locking API (using the WordPress Heartbeat API to handle control requests between concurrent users)
- Standardisation of UI elements and styles
- Automatic clean uninstall (all form settings, add-on settings and entry meta are removed automatically)
To use the Framework and get access to all these features we need to create WordPress plugin file and add a class that extends GFAddOn. If you’ve not built a WordPress plugin before, please take a quick look at the section on “Creating a Plugin” on the WordPress Codex.
The Add-On Framework requires some class variables to be configured.
Step 2: Add-On Settings
We need to add a settings page for the add-on that will allow the administrator to do three things:
- Activate and deactivate the results page
- Configure the connection details for the central server: URL, API Key and Private Key.
- Specify a custom string that will be used to identify the site on the results page on the central server
To create a settings page for an add-on override GFAddOn::plugin_settings_fields() and return an array with the configuration of the fields. The Add-On Framework will handle the rendering of the fields and also the storing and retrieval of the settings. The Settings API is fairly extensive so for further details of all the available options please check out the Settings API section of the documentation for GFAddOn.
The above code will generate the following settings page:
Step 3: The Results Page
A results page can be added in Gravity Forms with just a couple of lines of code. Override GFAddOn::get_results_page_config() and return the configuration array for the results page. In this case, we just need to set the title.
This will display the results page in the menu:
On the central site, the results page will be able to filter entries by site. Here are the entries from SiteA and SiteB respectively.
Step 4: Form Settings
Next let’s add some form settings so the administrator can activate remote aggregation on a form-by-form basis. Again, the Add-On Framework will handle the rendering of the page and the storing of the settings and the full details of all the available options can be found in the documentation for the Settings API.
This produces Form Settings for our add-on like this:
Step 5: Entry Meta
We’ll also need a way to identify the entries from each site so let’s add a custom property to the Entry object called gf_aggregator_id and update it with the value specified in the Site ID add-on setting. Entry Meta fields are added either by hooking into the gform_entry_meta filter or alternatively, by activating the Entry Meta feature of the Add-On Framework, and overriding GFAddOn::get_entry_meta().
This will allow the entries to be sorted on the entry list by the Site ID and filtered on the results page.
Step 6: Add-On Initialisation
The Add-On Framework contains a few methods we can use to execute code in the appropriate places during the loading of the page:
- Override this function to perform any tasks that need to be done before the WordPress action “init” fires.
- Override this function to perform tasks during WordPress initialisation. e.g. adding hooks.
- Override this function to perform tasks only in the admin area
Override this function to perform tasks only in the front-end
- - init_ajax()
Override this function to perform tasks only while processing ajax requests
For this add-on we’ll be using init_frontend() to hook into the gform_after_submission action.
Notice that, as the framework method is being overridden the parent method needs to be called to make sure the rest of the framework continues to load as expected.
Step 7: Web API – Storing the entries on the remote site
Every Gravity Forms installation comes with a Web API. It’s disabled by default so you’ll need to make sure you enable it on the settings page of the central server.
Rather than constructing all the URLs for the requests and handling the authentication signatures we can make life easier by using the Gravity Forms Web API Wrapper. Download it from from the GitHub repository
and add it to a folder called “includes” inside the plugin folder. The Web API Wrapper will handle the construction of the request and the authentication so we don’t have to.
The methods we’ll be needing for this project are create_form() and create_entry() but there are many more documented in the wrapper. For a more complete example of using the Web API wrapper check out the Web API Client.
We’ll be doing all the work for our add-on inside our after_submission() method:
A. Check the form settings to make sure this form is configured for remote aggregation
B. If the Form ID is empty in the settings then create the Form on the remote site. The remote Form ID is then saved in the settings.
C. Create the entry on the remote site making sure to identify the current site in the Entry Object
As a side note, a smarter approach would be to spin steps B and C off into a wp_cron task so that slow responses and timeouts can be handled gracefully without making the user wait, but of course that’s slightly out of scope for this introduction.
Step 8: API Functions – Deleting the local entries
There’s one final piece left to implement. That’s to delete the local Entry if permitted by the form settings.
In this case we’ll only be needing the delete_entry() function.
Complete Code Listing
The complete add-on is available for forking in the Github repository for Gravity Forms Aggregator.
View the complete listing: aggregator.php
Download the complete zip file of the add-on: gravityformsaggregator_0.1
Although this add-on is very simple, it’s not intended to be used in a production environment. It’s intended to be used primarily as a learning tool. I’m not intending to support this add-on or develop it further so if you do decide to use it in a production environment, please ensure that you do sufficient testing and that the security issues surrounding the API private key are taken into consideration.
- Form synchronisation: how will you handle changes to the form? If a field is added how will you propagate this change across all the sites?
- Security: at minimum use SSL in the WordPress admin
The Gravity Forms developer platform, consisting of the Add-On Framework, Actions and Filters, Web API and API functions stands on top of the giant’s shoulders that is WordPress and together they provide a highly extensible platform for the rapid development of form-based applications. The example project is simple one but it touches on each of the tools and demonstrates some best practices for working with Gravity Forms showing how the platform could be leveraged in the development of more complex applications.
I’ll be very happy to answer any questions you have about this tutorial in the comments. Please direct all specific questions about your project to the Gravity Forms technical support team.
- The views expressed here are my own and do not necessarily reflect those of Rocketgenius.
- Gravity Forms is a trademark of Rocketgenius
- WordPress is a trademark of The WordPress Foundation