I’ve made an add-on1 for Gravity Forms before. However, it wasn’t done by extending abstract class prepared by Gravity Forms for creating for add-ons: I was just hooking and filtering stuff, basically. This time I have an opportunity to do it by extending Gravity Forms’ prepared class for add-on.

1. The background

My employer in Hijapedia wants to use a plugin called WP-Subscribe Pro to increase the site’s traffic conversion into email subscriber so we can send them follow-up offering in the future. What the plugin does is displaying a blocking popup for first time customer after several seconds, when the user reach the end of article, or upon the page load. The submitted contact can be synced to MailChimp or GetResponse. I was asked to assess this decision and come up with this insight:

We can do better by tweaking Gravity Forms instead of using WP-Subscribe Pro because we already built custom plugin made to store email list, syncing all Gravity Forms’ input type name & email to that custom plugin, and syncing the email list to GetResponse and ArpReach

All the pros and cons considered, we decided to make a Gravity Forms add-on which adding what WP-Subscribe Pro’s does into Gravity Forms: displaying a selected Gravity Forms’ form as a blocking popup on page-load, after several seconds, or after reading a content when user visits the site for the first time.

2. How to make Gravity Forms add-on

Gravity Forms has prepared GFAddon class to be extended and this documentation has provided all for the complete coverage. Thus, I’ll only explain what I’ve used and what you can do from those class. All the stuff I’m going to explain can be found in this main plugin file of my Gravity Form add-on.

2.1. Getting started

You can get started by:

  1. Detecting whether GFForms class exists.
  2. Calling GFForms::include_addon_framework() method.
  3. Extending GFAddon class, which is made specifically to make add-on creation easier.
  4. Call the newly created extended class.

2.2. Methods that I used

Add-on creation is basically a process of overriding default methods. The methods that i used:

2.2.1 init_frontend()

Easily add code that will be displayed on public facing side of WordPress:

protected function init_frontend(){
    parent::init_frontend();

    add_action( 'wp_enqueue_scripts',                           array( $this, 'frontend_scripts' ) );
    add_action( 'wp_footer',                                    array( $this, 'display_popup_form' ) );
}

2.2.2 init_admin()

Adding code that will be called on dashboard. You’ll need to limit its scope, tho. I did it by simply detecting query string:

protected function init_admin(){
    parent::init_admin();

    // Only do this on Gravityforms Popup page
    if( isset( $_GET['page'] ) && isset( $_GET['subview'] ) && 'gf_settings' == $_GET['page'] && 'gravityforms-popup' == $_GET['subview'] ){

        wp_enqueue_media();
        wp_enqueue_script( 'gravityforms-popup-dashboard', $this->get_base_url() . "/js/gravityforms-popup-dashboard.js", array( 'jquery' ), $this->_version, true );

    }
}

2.2.3 init_ajax()

Adding ajax action by hooking wp_ajax_ callback:

protected function init_ajax(){
    parent::init_ajax();

    add_action( 'wp_ajax_gravityforms_popup_update_cookie',     array( $this, 'set_cookie_value' ) );
}

2.2.4 plugin_settings_fields()

Easily creating options panel tab on `Dashboard > Forms > Settings > {your_custom_tab} by returning formatted array:

/**
 * Plugin settings
 * 
 * @access public
 */
public function plugin_settings_fields(){
    $setting_fields = array(
        array(
            "title" => __( '', 'gravityforms-popup' ),
            "fields" => array(
                array(
                    'label'          => __( 'Select Form:', 'gravityforms-popup'),
                    'type'           => 'select',
                    'name'           => 'gform',
                    'default_values' => $this->get_setting( 'gform', 0 ),
                    'choices'        => $this->choices_gforms()
                ),
                array(
                    'label'          => __( 'Seconds To Appearance:', 'gravityforms-popup'),
                    'type'           => 'number',
                    'name'           => 'seconds_to_appearance',
                    'default_value'  => 10
                ),
                array(
                    'label'          => __( 'Show Popup on:', 'gravityforms-popup'),
                    'type'           => 'checkbox',
                    'name'           => 'popup_appearance',
                    'default_value'  => true,
                    'choices'        => array(
                        array(
                            'label'  => __( 'Front Page', 'gravityforms-popup' ),
                            'name'   => 'appearance_is_front_page'
                        ),
                        array(
                            'label'  => __( 'Single Posts, Pages, and other Post Types', 'gravityforms-popup' ),
                            'name'   => 'appearance_is_singular'
                        ),
                        array(
                            'label'  => __( 'Category, Tags, and Custom Taxonomy Page', 'gravityforms-popup' ),
                            'name'   => 'appearance_is_archive'
                        ),
                        array(
                            'label'  => __( 'Search Results', 'gravityforms-popup' ),
                            'name'   => 'appearance_is_search'
                        ),
                        array(
                            'label'  => __( '404 Not Found Page', 'gravityforms-popup' ),
                            'name'   => 'appearance_is_404'
                        ),
                        array(
                            'label'  => __( 'When user reaches the bottom of the page', 'gravityforms-popup' ),
                            'name'   => 'display_on_bottom_page'
                        ),
                    )
                ),
                array(
                    'label'         => __( 'Initial Image:', 'gravityforms-popup' ),
                    'type'          => 'select_image',
                    'name'          => 'initial_image'
                ),
                array(
                    'label'         => __( 'Update Cookie:', 'gravityforms-popup' ),
                    'type'          => 'update_gravityforms_popup_cookie_type',
                    'name'          => 'update_cookie'
                )
            )
        ),
    );

    return $setting_fields;         
}

This will handle the value saving mechanism. More importantly, besides using the pre-configured input field type, you can create custom input by providing method which is prefixed by settings_{your_type_name}. Assume you’d like to create input image mechanism (like I did), you can use this array to define the input:

array(
    'label'         => __( 'Initial Image:', 'gravityforms-popup' ),
    'type'          => 'select_image',
    'name'          => 'initial_image'
)

Then adding this method to handle the custom input and saving mechanism:

public function settings_select_image( $field ){

}

2.3 Making the plugin

With those four provided methods (and other custom methods), I can easily create a Gravity Forms add-ons. How it works is basically:

  1. Register a settings tab through plugin_settings_fields() method
  2. Build custom type callback2.
  3. Enqueue custom script on the admin page3.
  4. Based on the value saved, hook appropriate code in init_frontend() and init_ajax()

That’s pretty much how I did it.

3. Feedback for Gravity Forms developer

Based on my experience developing this add-on for Gravity Forms, GFAddon’s method speeds the development time a lot. However, there are some missing methods specifically callback for handling various custom form input that can be added:

  1. A method for providing Gravity Forms’ forms list for checkbox / radio / select choices
  2. A settings_ callback for input[type=“number”]
  3. A settings_ callback for uploading / selecting image thru WordPress’ media uploader

I couldn’t find these three methods provided by default, so I make my own method instead (well that’s how it supposed to work, actually). However, I think that there’s a probability that other add-on developer need them as well.

4. See it yourself

Here’s how the add-on looks like. It is called Gravity Forms Popup:

Settings page
Settings page
Filled settings
Filled settings
Gravity Forms Popup with Clickable Initial Image
Gravity Forms Popup with Clickable Initial Image
Gravity Forms Popup's Form
Gravity Forms Popup’s Form

Add-on Page | Download the add-on on GitHub.


  1. Plugin for extending another plugin’s functionality 

  2. If necessary. In my add-on case, it’s necessary 

  3. Idem 

Share Your Thought