Advanced Gravity Forms: Easily create a custom post type from form submission

Posted by Lloyd Jones
Last updated
Create a custom post type with Gravity Forms - the coders' way

Do you have a WordPress site that uses Custom Post Types for content, and want to link the successful submission of a Gravity Forms entry to the creation of one of these custom post types – and populate the post’s fields with the submitted content?

Well, that’s what I am going to show you how to do today.

I know that WordPress plugins exist for this purpose, but in my experience, they’re rigid and don’t allow the total freedom of coding things yourself. This method is also extendible (as you’ll see at the bottom of this post).

Here are some assumptions made when writing this post:

  • You have Gravity Forms installed (preferably the latest version)
  • You already have a custom post type (and for this example, it only needs to support “title”)
  • You have custom meta boxes installed and set up
  • You are comfortable with handling gravity forms’ hooks/filters, to a degree
  • You want to create a post and publish it upon successful submission of your gravity form

Please note:
I use Gravity Forms extensively, and think they’re excellent – I recommend using them. Here is an affiliate link to Gravity Forms: “Click here to visit rocketgenius.“. If you like them and want to purchase, I’ll get 20% of the sale (hooray!).

Anyhow, lets begin..

Here are the steps:

1) Note the custom fields used in your custom post type

function listing_metaboxes( array $meta_boxes ) {

	// Start with an underscore to hide fields from custom fields list
	$prefix = '_sitemeta_';
		
		$meta_boxes[] = array(
			'id'         => 'cat-meta', //ID of the metabox
			'title'      => 'Cat Information', //Title that will appear in editor
			'pages'      => array( 'cat'), // Custom post type
			'context'    => 'normal', //Main column in the editor
			'priority'   => 'high', //Priority..
			'show_names' => true, // Show field names on the left
			'fields'     => array(
				array(
					'name' => 'Cat colour',
					'desc' => 'The colour of the cat',
					'id' => $prefix . 'colour',
					'type' => 'text_medium',	
				),
				array(
					'name' => 'Cat personality',
					'desc' => 'Describe the cat\'s personality in detail',
					'id' => $prefix . 'personality',
					'type' => 'textarea',	
				),
				array(
					'name' => 'Cat smell',
					'desc' => 'Cat\'s smell',
					'id' => $prefix . 'smell',
					'type' => 'text_medium',	
				),
			)
		);
		return $meta_boxes;
}

In my example above (in functions.php), I’m limiting these meta boxes to the custom post type “cat”, which has three custom fields – “_sitemeta_colour”, “_sitemeta_personality”, “_sitemeta_smell”.

(I’m using custom meta boxes so that the custom fields can be interacted with, via the “add new ” area in the WordPress dashboard.)

So, we have our custom fields:

  • “_sitemeta_colour”
  • “_sitemeta_personality”
  • “_sitemeta_smell”

Next:

2) Create a gravity form containing these same fields and note its ID and field IDs

cat-form

To start, create a new form in Gravity Forms, and make sure that you set all fields to mandatory/”required”, so that the custom post type definitely contains data for each of its fields from the form’s entry.

Note the form’s ID (1. in the image above), and the field IDs by hovering over them (2. in the image above). For our example, we’ve observed the following information:

  • Form ID: 5
  • Name field ID: 4
  • Colour field ID: 1
  • Personality field ID: 2
  • Smell field ID: 3

Along with these custom fields from step 1.:

  • “_sitemeta_colour”
  • “_sitemeta_personality”
  • “_sitemeta_smell”

3) Go to your theme’s functions.php file
This is usually found in /wp-content/themes/YOUR-THEME-NAME/functions.php

4) Add the following code snippet

add_action("gform_after_submission_5", "create_cat_from_submission", 10, 2);
function create_cat_from_submission($entry, $form){
	//First need to create the post in its basic form
	$new_cat = array(
		'post_title' => ucwords($entry[4]),
		'post_status' => 'publish',
		'post_date' => date('Y-m-d H:i:s'),
		'post_type' => 'cat'
	);
	//From creating it, we now have its ID
	$theId = wp_insert_post($new_cat);
	//Now we add the meta
	$thePrefix = '_sitemeta_';
	update_post_meta($theId, $thePrefix.'colour', ucwords($entry[1]));
	update_post_meta($theId, $thePrefix.'personality', ucwords($entry[2]));
	update_post_meta($theId, $thePrefix.'smell', ucwords($entry[3]));
}

Obviously you’d replace all custom fields, gravity form field IDs, custom post type and gravity forms form ID with your own..

The ‘ucwords()’ function wrapped around each $entry is just to make the entries display nice and consistently, with the first letter capitalised.

What’s going on.. ?

Inside this function (create_cat_from_submission), we’ll access the $entry array object of the form, which contains the results of the form submission.

If you flick back to the form creator image above, you’ll see that each field has an ID (which we noted down). The entry object’s elements ($entry[1], $entry[2], etc.) match up with these IDs:

field-matchups

The function ‘update_post_meta’ is called (even if the custom field is empty, as it then creates it) to insert the form entry data into the custom post type’s custom field of this name:

update_post_meta($theId, $thePrefix.'colour', ucwords($entry[1]));

The first parameter is the post’s ID, which we’ve got from wp_insert_post(), the second parameter is the custom field name (“_sitemeta_colour”, in this case). I’ve used the “prefix” variable because I’m lazy and didn’t want to type “_sitemeta_” out each time.. Like I’m doing now..
The third parameter is the form field with the ID of 1., which is (look up the page) our ‘Colour’ form field.

Excellent – we’ve now linked the form’s entry to the custom post type!

That’s the basics done with. But how about if you want to link images uploaded via the Gravity Form to the custom post type? Okay, here goes:

  • 1. Create a file upload field in the Gravity Forms form editor, click on it and enable “Multi-file upload”. Note the ID of this field, like we did above for the other fields. For our example, we’ll use 5 as our field ID.
  • 2. Create another metabox, like in our example above, but make its ‘type’ be ‘file_list’ and give it a name – I’ll use ‘photos’
  • 3. Add this code to your functions.php (same code as above, but with some additions):
    add_action("gform_after_submission_5", "create_cat_from_submission", 10, 2);
    function create_cat_from_submission($entry, $form){
    	//First need to create the post in its basic form
    	$new_cat = array(
    		'post_title' => ucwords($entry[4]),
    		'post_status' => 'publish',
    		'post_date' => date('Y-m-d H:i:s'),
    		'post_type' => 'cat'
    	);
    	//From creating it, we now have its ID
    	$theId = wp_insert_post($new_cat);
    	//Now we add the meta
    	$thePrefix = '_sitemeta_';
    	update_post_meta($theId, $thePrefix.'colour', ucwords($entry[1]));
    	update_post_meta($theId, $thePrefix.'personality', ucwords($entry[2]));
    	update_post_meta($theId, $thePrefix.'smell', ucwords($entry[3]));
    	
    	$thePhotos = json_decode($entry[5]);
    	$firstPhoto = true;
    	
    	foreach($thePhotos as $aPhoto){
    		$path = parse_url($aPhoto, PHP_URL_PATH);
    		$aPhotoPath = $_SERVER['DOCUMENT_ROOT'] . $path;
    		$filetype = wp_check_filetype($aPhoto);
    	
    	    // The arguments for the photo
    	    $args = array(
    	        'post_mime_type' => $filetype['type'],
    	        'post_title'     => ucwords($entry[4]), //The photo's title. I'm using the same title as the post
    	        'post_content'   => '',
    	        'post_status'    => 'inherit'
    	    );
    		header('Content-Type: text/html');
    	    $thumb_id = wp_insert_attachment( $args, $aPhotoPath,  $theId );
    		
    	    $metadata = wp_generate_attachment_metadata( $thumb_id, $aPhotoPath );
    	    wp_update_attachment_metadata( $thumb_id, $metadata );
    		
    		$finalPhotos[$thumb_id] = $aPhoto;
    		
    		// Set the first image uploaded as the post thumbnail
    		if ( $firstPhoto )
    	    {
    			set_post_thumbnail( $theId, $thumb_id);
    	        $firstPhoto = false;
    	    }
    	} 
    	update_post_meta($theId, $thePrefix.'photos', $finalPhotos);
    	
    }
    

Done!

Okay, here’s what is going on:

We firstly have to json_decode() the entry and store it in an array:

$thePhotos = json_decode($entry[5]);

As the file uploader provides the file(s) in JSON.

We then iterate through the array, and for each iteration, we do the following:

$path = parse_url($aPhoto, PHP_URL_PATH);
$aPhotoPath = $_SERVER['DOCUMENT_ROOT'] . $path;

Get the absolute path to the image uploaded.

Create the photo array:

  $args = array(
	        'post_mime_type' => $filetype['type'],
	        'post_title'     => ucwords($entry[4]), //The photo's title. I'm using the same title as the post
	        'post_content'   => '',
	        'post_status'    => 'inherit'
	    );

Set our HTTP Header so that the site doesn’t decide to just output the uploaded image(s) rather than show our form:

header('Content-Type: text/html');

Get the thumbnail ID, which we use to associate the path to the image with the thumbnail, then update the attachment metadata, and then add the thumbnail ID to an array of IDs:

$thumb_id = wp_insert_attachment( $args, $aPhotoPath,  $theId );
		
	    $metadata = wp_generate_attachment_metadata( $thumb_id, $aPhotoPath );
	    wp_update_attachment_metadata( $thumb_id, $metadata );
		
		$finalPhotos[$thumb_id] = $aPhoto;

Then set the first image uploaded as the post’s thumbnail / featured image:

if ( $firstPhoto )
	    {
			set_post_thumbnail( $theId, $thumb_id);
	        $firstPhoto = false;
	    }

And finally, insert this array of thumbnail IDs into the ‘photos’ custom field, so that the custom metabox can see the images we’ve uploaded:

update_post_meta($theId, $thePrefix.'photos', $finalPhotos);

That’s it!

If you’ve followed this article all of the way through, you’ll have successfully linked your gravity form’s successful entry with the creation of a custom post type!

If you like what you’ve read, have any improvements/suggestions, or just want to share your experience with this method, leave a comment below!

UPDATE

A few people have emailed asking what something like this would be useful for.. Well, here are a few examples from my own coding experience:

– Creating a new “listing” custom post type, as on http://puppies.co.uk after a user fills out the form to create a new listing

– Creating a new custom post type of a purchase for my Gravity Forms + DigitalOcean integration plugin after form submission

– Creating a new directory listing for a recent private outsourcing project

It’s actually very useful. Let me know what you’ve done with this method!

16 Comments

Thad

Thanks for sharing this, I’ve been using the “Gravity Forms + Custom Post Types” plugin for awhile but the author seems to have abandoned development. I’d rather do this on my own anyway 🙂

Reply
Lloyd

Hey Thad,

No problem! I totally prefer doing it my own way as you’re not limited by the ‘confines’ of the plugin. So much more customisable!

Reply
Louise Desmarteau

Hello Lloyd,

I’ve implemented your code and its working for me, EXCEPT, each custom post submitted through the form, is also creating a draft regular post. So, my CPT is doctors, that works great. Then, when I click the Posts tab in wp-admin, I’m seeing something like this:

Title – Untitled_23 – Draft
A category is being assigned
There is no content when I view the post

This was not happening before adding the code.

Also, the posts are always set to scheduled. But, in your code I thought it would set them to published. Am I doing something wrong there as well?

Thanks,
LD

Reply
Robert

Thanks for sharing this, it was very useful for us to integrate gravity forms to submit a directory listing. I did run into an error with the image, where the message stated I was calling an undefined function wp_generate_attachment_metadata(). I added this above the function call which fixed the issue.

require_once( ABSPATH . ‘wp-admin/includes/image.php’ );

Thanks so much for providing this tutorial!

-Robert

Reply
Lloyd

Hi Robert,

Thanks for the tip there – I’ve sometimes had to add that myself actually!

No problem at all – there’ll be more to come when I have the time!

Cheers,
Lloyd

Reply
Gregg Shanefelt

I am having a similar issue to Louise. Would you mind following up with what your solution for her site?

Thanks in advance, this saved me a lot of time.

Reply
Bashi

I have exactly the same problem: each submitted custom post creates also a draft regular post. Thumbnail image is inside of a regular post and all other information inside of a custom post.

What is the fix for this?

Reply
Dave

I am having a similar issue to Louise and Gregg where it adds a untitled post to “Posts”. All submission to CPT is perfect. Would you mind following up with what your solution for their sites?

This was awesome and got me going on the right track – saved me a lot of time too!

Thanks in advance.

Reply
Lloyd

Hi Dave,

We actually didn’t work this one out, as I couldn’t replicate the issue. I thought that maybe there was a clash with another plugin.

If you have a dev area with FTP, drop me a reply on here and I’ll communicate with you via email if you’d like me to take a look.

Thanks,
Lloyd

Reply
Asim

Were you ever able to figure out why the posts were showing up as Scheduled? I just implemented your code but am having trouble with the posts being scheduled approximately 8 hours out.

Reply
Lloyd

Hi Asim,

I wasn’t unfortunately – It’s not something I was able to replicate with Custom Post Types. I’ll give it a look when I have some free time to see if I can figure it out!

Reply
Peter

Hi everyone,

I had the same issue with untitled posts being created but solved by removing all post fields and replacing them with plain text or paragraph fields (including the post image upload and replacing it with a standard file upload).

So, replace those and then update your field IDs and it _should_ no longer create the untitled, standard posts!

Hope that helps

Reply

Leave a Reply

Your email address will not be published. Required fields are marked *