How to Create Data Entry Forms for WordPress with Contact Form 7

In two recent projects I’ve encountered a need to enable website visitors to create new information on the website. This isn’t typical WordPress stuff so let me describe a specific scenario:

  1. A form is presented on the website for a visitor to fill out.
  2. When that form is submitted the information in it is processed and automatically stored in either a standard post or a custom post-type.
  3. The new post can then (assuming it was created in a published state) be found and viewed on the website itself without any manual intervention.

The first part is fairly easy to do – I’ve been using Contact Form 7 for a long time as a forms plugin. The 3rd part is standard WordPress behavior. The challenge was in the 2nd part – capturing and processing the information. I am happy to say that not only is it possible but it is actually very simple to do (for a WordPress theme/plugin developer).

What tipped me off and uncovered the solution was another plugin called Contact Form 7 Database Extension which stores form information submitted using Contact Form 7 in a database. I examined the code and found what I was looking for.

Contact Form 7 has an action hook called wpcf7_before_send_mail which is passed an array that includes the form title and an array of submitted data. All you need to do is hook into this action and do … whatever you want to do.

function my_wpcf7_save($cfdata) {
	$formtitle = $cfdata->title;
	$formdata = $cfdata->posted_data;	
	if ( $formtitle == 'expected-form-title') {
		// access data from the submitted form
		$formfield = $formdata['fieldname'];
		// create a new post
		$newpost = array( 'post_title' => $formdata['formfield-containing-title'],
		     		  'post_content' => $formdata['formfield-containing-content'],
		    		  'post_status' => 'publish');
		$newpostid = wp_insert_post($newpost);
		// add meta data for the new post
		add_post_meta($newpostid, 'custom-field1', $formdata['formfield-containing-customfield1']);
		add_post_meta($newpostid, 'custom-field2', $formdata['formfield-containing-customfield2']);
add_action('wpcf7_before_send_mail', 'my_wpcf7_save',1);

This function demonstrates:

  • A save function hooked into the contact-form action.
  • Conditional testing of the submitted form so that other forms are not mistakenly processed
  • Using wp_insert_post to create a new post based on form data.
  • Using add_post_meta to add custom fields based on form data.

Once you get the hang of it you can do anything you want inside WordPress. I’ve used this technique for creating posts, custom post-types and even for creating a customized user registration form embedded into the front end of a website (with custom fields added to the user profile too).

One last thing I wanted to add but have not yet figured out is how to automatically redirect the browser to the new post. I tried using wp-redirect but that didn’t work. I am guessing it created some kind of conflict with the plugin which has not yet completed it’s processing. I did find this redirection technique within the plugin but I do not know how to use it to redirect to the actual post.


  1. Marc
    Posted March 24, 2011 at 1:50 pm | Permalink

    Thanks, this is what I was looking for!
    However, is it possible to add a featured image to the post automatically with an uploaded image in contact form7?
    Thanks in advance.

    • iamronen
      Posted March 25, 2011 at 5:24 am | Permalink

      The project I was working on was put on hold so I didn't get around to exploring images. First you have to figure out how to get to the files (maybe debug the contents of the contact form image fields) then you probably need to use WordPress API functions to both add the images to the post (and in doing so store them in the media library?) and then set a featured image.

      If you do figure this out it would be great if could leave a comment with what you found :)

      Good luck!

  2. Posted August 18, 2011 at 3:45 am | Permalink

    This is EXACTLY what I've been looking for!

    I just went to give it a test and I think I'm missing something here… the extra semi-colons within a couple of the lines cause the code to fail. Am I supposed to be editing those sections? I don't believe I've seen those tags before.

    Might you be able to elaborate just a little bit on how I could implement this in my WP site? I would greatly appreciate it!

    Thanks very much,

    • iamronen
      Posted August 18, 2011 at 4:41 am | Permalink

      I'm glad you found this useful Andrew.

      It does however take a bit of WordPress coding skill to get it working.

      For sure you would need to adjust the formdata array labels to match those of the form you've created and are processing. The ones I've included are to just to demonstrate the code structure.

  3. Warren
    Posted October 14, 2011 at 1:05 pm | Permalink


    Your post describes exactly what it is I want to do, although it's not working for me. I'm no plugin developer so I'm sure I'm probably doing something wrong somewhere.

    Can you advise where I need to paste the above code? I have pasted it into the theme's function.php file as well as CF7's controller.php file, and each time it breaks the website, resulting in a 'HTTP Error 500.0 – Internal Server Error'.

    I'm sure its my ignorance thats causing the problem, so any help/advice would be much appreciated.

    Kind regards,


    • iamronen
      Posted October 14, 2011 at 5:12 pm | Permalink

      Hello Warren,

      The code can go in the functions.php file of your theme, you should not modify any plugin files to get it to work.

      But the code is not ready to go as is … you need to modify it to be compatible with the form(s) you are trying to process. The actual data available and that you can access in $formdata depends on the field names in your form.

      A basic understanding of PHP is needed to implement this.

      I hope this works out for you eventually.

      All Things Good


  4. Colir
    Posted October 27, 2011 at 9:39 am | Permalink

    i'm asking me if with this kind of trick i can use contact form 7 as a registration form.
    The idea will be to create a new form and post information on wordpress default registration form and catch back the returned error to display error whithin contact form 7 (if there are error)

    do you think it's possible ?

    • iamronen
      Posted October 27, 2011 at 4:25 pm | Permalink

      I am not sure that I understand you completely … but I have used this to create a custom registration form that creates both posts and users within WordPress. Once you catch the form you can process it however you like and do pretty much anything the WordPress API gives you access to.

  5. Colir
    Posted October 27, 2011 at 4:48 pm | Permalink

    huho ! this interest me a lot
    you say "I have used this to create a custom registration form that creates both posts and users within WordPress"

    If i well understand, you create user automatically with a contact form 7 form ?
    this is exactly what i'm looking form (and also use contact form 7 as a login form)

    can you tell me more about the process ?


    • iamronen
      Posted November 2, 2011 at 3:48 pm | Permalink

      When you process the form containing the user information you collected you can call a WordPress API function wp_insert_user that will create a new user for you. Please note that you should probably do some kind of validation to make sure the user does not already exist.

  6. Colir
    Posted November 2, 2011 at 11:59 am | Permalink

    huho ! this interest me a lot !
    Can you explain how you create a new user using a contact form 7 ?
    it's possible to do this without that contact form 7 send a mail ?

    thanks for your help !

    • iamronen
      Posted November 2, 2011 at 3:49 pm | Permalink

      I don't know if it's possible to prevent contact-form from sending an email however you can send the email to a garbage account.

  7. Colir
    Posted November 2, 2011 at 4:04 pm | Permalink

    thanks. and sorry for the double comment

  8. jared
    Posted November 7, 2011 at 11:18 pm | Permalink

    Where did you get the variable $cfdata? Your post about the cf7 is hook helpful but I'm struggling with how to pass the cf7 form data into a variable which I will then pass into my HTTP request to a rails api. How did you access the cf7 data array?

    • iamronen
      Posted November 8, 2011 at 5:21 am | Permalink

      The plugin action, to which this function is hooked, passes the form data in as an object. Notice in the add_action line at the end the number "1" indicates that one variable is expected – that is the object from the plugin.

  9. Markus
    Posted March 5, 2012 at 6:01 pm | Permalink

    I want inser the post from contact form 7. Where must inser your function? In function.php of template? my_wpcf7_save is the name of form?

    How can make format layout of the post?
    Nome: name
    Surname: surname
    list checkbox

    • iamronen
      Posted March 6, 2012 at 5:04 pm | Permalink

      insert function can be in functions.php.
      my_wpcf7_save is the name of the function I used in this example to process the form … it is hooked into one of the plugins hooks.
      layout of the post is completely in your hands … you process the form data and generate practically any HTML you want.

  10. Ron
    Posted March 14, 2012 at 1:00 pm | Permalink

    Excellent function. Thx.

    I discovered – from someone else – how to prevent cf7 sending mail – just pop

    $cfdata->skip_mail = true;

    …anywhere in the processing for the 'expected-form-title'


    • iamronen
      Posted March 14, 2012 at 2:14 pm | Permalink

      thank you for the skip-mail tip :) great stuff :)

  11. Caroline
    Posted March 14, 2012 at 6:35 pm | Permalink

    Anyone getting an error is getting it because the following lines:
    add_post_meta($newpostid, 'custom-field1', $formdata['formfield-containing-customfield1'];
    add_post_meta($newpostid, 'custom-field2', $formdata['formfield-containing-customfield2'];

    are not closed correctly. They should read as such:

    add_post_meta($newpostid, 'custom-field1', $formdata['formfield-containing-customfield1']);
    add_post_meta($newpostid, 'custom-field2', $formdata['formfield-containing-customfield2']);

    Notice the closed parenthesis at the end of the unique paramater.

    • iamronen
      Posted March 15, 2012 at 4:32 pm | Permalink

      Thank you for pointing out that error Caroline – I've corrected it in the sample code :)

      • Caroline
        Posted March 16, 2012 at 1:01 am | Permalink

        My pleasure! Thanks for the great tip/tutorial!

  12. Posted May 3, 2012 at 10:38 am | Permalink

    Great post!

    I noticed another small error in the script:

    $formfield = $formdata['fieldname']

    It should be ended with a semicolon.

    • iamronen
      Posted May 6, 2012 at 5:35 am | Permalink

      thank you very much Nick … corrected :)

  13. Posted May 3, 2012 at 10:40 am | Permalink

    Same goes for the following line:

    $newpostid = wp_insert_post($newpost)

    • iamronen
      Posted May 6, 2012 at 5:36 am | Permalink

      … and corrected :)

  14. Posted May 26, 2012 at 5:40 am | Permalink

    wow…. awesome.
    this is so simple…
    thank you so much..
    and about security and everything. nonce is already provided by cf7 right?

    • iamronen
      Posted May 26, 2012 at 5:50 am | Permalink

      Glad it helped :)

      I don't know about security implications. I would hope that the WordPress update functions provide some kind of inherent filtering but I haven't looked into it.

  15. Posted September 18, 2012 at 3:45 pm | Permalink

    For anyone who just copied and pasted the code ( or for anyone who is about to ) change ">" to ">" this will correct the script.

    • iamronen
      Posted September 18, 2012 at 4:16 pm | Permalink

      Thank you Nicole … I've tried fixing that a few times … but something keeps reverting to the codes instead of the characters. I finally gave up on it :)

      • Posted September 18, 2012 at 4:43 pm | Permalink

        I know this might sound like a dumb question but in this area ['formfield-containing-title'] you should put your own information right?

        I know that sounds kind of like a noobish question but i am confusing myself probably a little bit. … It happens a lot. lol

        • iamronen
          Posted September 18, 2012 at 5:07 pm | Permalink

          Yes that is just a placeholder. If you want to use one of your form fields as a title – that's how you would do it.
          Of course you can programatically generate any title you want by processing additional fields from the form … or what not.

          It can be tricky … great that you are giving it a try :)

          • Posted September 18, 2012 at 7:37 pm | Permalink

            If you wanted to add more than one form field in the content area how would you do that?

          • iamronen
            Posted October 8, 2012 at 5:03 pm | Permalink

            The line that has ‘post_content’ => $formdata['formfield-containing-content'] is a very simplified example. You could create a content variable that aggregates/processes/tests any number of form fields and then use that as your content source.

          • Posted October 9, 2012 at 3:28 pm | Permalink

            I have found that this works if you want to use consecutive information … or more than one form piece in the same area

            'post_content' => $formdata['formfield-content1']. 'something else here … even a space ' .$formdata['formfield-content2'];

            Same would go with adding post meta or aka custom fields.

  16. Posted October 8, 2012 at 4:50 pm | Permalink

    Great post! I just implemented a membership signup form using ideas from this post.
    – The form was built with Contact Form 7.
    – I created a custom content type form membership data with the Types plugin.
    – I added a function like the one in this post.

    It works great! I was even able to add the code for the PayPal button to the message indicating that the form was submitted successfully. People signing up submit the form and then go right to PayPal to pay.

    • Mike
      Posted November 9, 2012 at 8:37 am | Permalink

      Hi Dan, could you tell more about this? I'm just beginner at PHP but would love to do this on the site i'm building. I understand the procedure, just not sure where the code needs to be replaced. And how are you integrating Types plugin with it? Thanks!

    • Posted December 20, 2012 at 1:35 pm | Permalink

      Types is just being used to create the custom post type. There's really no integration between Types and CF7.

      To create custom posts from CF7 form input, you use code like in the post. Put that code into functions.php.

  17. Jamie
    Posted October 18, 2012 at 6:51 pm | Permalink

    I am very new to wordpress and codes and all that jazz,
    I've opened the editor for contact form 7, now I'm just trying to figure out where on earth to find the my_wpcf7_save, there's about 100 different pages! sorry for being such a new

    • iamronen
      Posted October 19, 2012 at 7:36 am | Permalink

      Hello Jamie,

      Welcome to WordPress and codes and all that jazz :) It's a constant journey of learning. You are looking in the wrong place. To get acquainted with this topic you will need to look into theme and plugin development ( )and action hooks where you can create your own code. Action hooks are a mechanism within WordPress which make it possible for other developers to add their own functionality to existing functionality. In this case "my_wpcf7_save" is an action hook within the contact form plugin which you can use to access and process the data submitted in the form.

  18. Ros
    Posted November 1, 2012 at 1:55 am | Permalink

    Thank you for this code. I was stuck at this crucial step. My form has 17 custom fields plus 5 standard wp_insert_post fields as hidden values. In your code, I used add_post_meta for the 17 custom fields, added the form title to $formtitle and the corresponding fields to the $newpost array. What data goes into the $formfield variable? Is this 1 line or 5 or 17 unique lines or should I just leave this line as is? Thank you for your help. It is appreciated.

    • iamronen
      Posted November 1, 2012 at 7:39 am | Permalink

      That line is just an example of how to capture information from the form array into a variable you can then manipulate and process and what not. In your case it is redundant. Sounds like you got the hang of it :)

  19. Mike
    Posted November 9, 2012 at 8:30 am | Permalink

    This is amazing.. just what i want to do. I was looking for a method to use CF7 as an advanced registration form.

    However i am just starting with PHP and have some doubts.. i hope you can help me, please!

    Where exactly would the wp_insert_user go, in your example above (if we discard the option of publishing as a post). And what about wp_create_user , is that not being used?

    Could you maybe post a basic example of using the form as registration? I know you put a lot of effort into this and i'm really thankful, even if i can't use it like this, but it helps to learn more about WP.

    • iamronen
      Posted December 20, 2012 at 7:08 am | Permalink

      Mike your questions go beyond the scope of this post and an answer that would fit in a comment. You would need to continue getting acquainted with PHP development and then learn about WordPress theme and/or plugin development to implement what it described in this post. You may want to start looking around here:

  20. Andre
    Posted January 29, 2013 at 12:08 am | Permalink

    Hey, great post; this has helped me alot, ive customised the code to allow for customised user-profiles set up in the blog section (so it seems like like a user info search, rather than blog) however there is one thing i havent figured out yet and was wondering if you could help.

    How would i code "adding the new post to a certain category/categories"?

    So, they select an option from a dropdown, and whatever they select is what the category of the post is (i will have predefined categories and name the dropdown entries the same as the category, so all i need is the code to let the form know to add the category to the post

  21. katia
    Posted February 11, 2013 at 12:37 am | Permalink


    I tried to implement this solution. To start with, I just put this code in functions.php

    function wpcf7_do_insert_post($wpcf7) {
    add_action("wpcf7_before_send_mail", "wpcf7_do_insert_post");

    I tried too with this code :
    add_action("wpcf7_mail_sent", "wpcf7_do_insert_post");

    But it isn't work fine : the email sends fine, but it just stays with the little spinning circle next to the submit button. Any help would be greatly appreciated

    Sorry, my English is not very good

  22. Alain
    Posted May 21, 2013 at 3:25 pm | Permalink

    Thank you for sharing this!

    Much appreciated!

  23. Maor
    Posted June 12, 2013 at 1:26 am | Permalink

    Is this action of wpcf7_before_send_mail is safe to use when adding data to db? What about data sanitation , does CF7 does it?


  24. Posted December 9, 2013 at 8:44 pm | Permalink

    I have a Contact Form 7 for bands to fill out and I want it to add the data directly to the database. I am a newbie, but feel I am close. Here is my code can you point me in the right direction. Thank You.

    add_action(“wpcf7_before_send_mail”, “wpcf7_do_something_else_with_the_data”);
    function wpcf7_do_something_else_with_the_data(&$wpcf7_data)

    // Everything you should need is in this variable

    // I can skip sending the mail if I want to…
    $wpcf7_data->skip_mail = false;

    function wbd_artist_save_postdata( $post_id ) {
    if ( defined( ‘DOING_AUTOSAVE’ ) && DOING_AUTOSAVE )

    if ( !isset( $_POST['wbd_artist_details_nonce'] ) || !wp_verify_nonce( $_POST['wbd_artist_details_nonce'],

    plugin_basename( __FILE__ ) ) )

    if ( ‘page’ == $_POST['post_type'] )
    if ( !current_user_can( ‘edit_page’, $post_id ) )
    if ( !current_user_can( ‘edit_post’, $post_id ) )

    $post_ID = $_POST['post_ID'];

    $posted_artisttype = sanitize_text_field( $_POST['wbd_artist_details_artisttype'] );
    add_post_meta($post_ID, ‘_wbd_artist_details_artisttype’, $posted_artisttype, true) or
    update_post_meta($post_ID, ‘_wbd_artist_details_artisttype’, $posted_artisttype);

    $posted_datestart = sanitize_text_field( $_POST['wbd_artist_details_datestart'] );
    add_post_meta($post_ID, ‘_wbd_artist_details_datestart’, $posted_datestart, true) or
    update_post_meta($post_ID, ‘_wbd_artist_details_datestart’, $posted_datestart);

    $posted_dateend = sanitize_text_field( $_POST['wbd_artist_details_dateend'] );
    add_post_meta($post_ID, ‘_wbd_artist_details_dateend’, $posted_dateend, true) or
    update_post_meta($post_ID, ‘_wbd_artist_details_dateend’, $posted_dateend);

    $posted_origin = sanitize_text_field( $_POST['wbd_artist_details_origin'] );
    add_post_meta($post_ID, ‘_wbd_artist_details_origin’, $posted_origin, true) or
    update_post_meta($post_ID, ‘_wbd_artist_details_origin’, $posted_origin);

    $posted_label = sanitize_text_field( $_POST['wbd_artist_details_label'] );
    add_post_meta($post_ID, ‘_wbd_artist_details_label’, $posted_label, true) or
    update_post_meta($post_ID, ‘_wbd_artist_details_label’, $posted_label);

    $posted_grpmembers = wbd_posted_group_array($_POST,’wbd_artist_details_grpmembers_’);
    add_post_meta($post_ID, ‘_wbd_artist_details_grpmembers’, $posted_grpmembers, true) or
    update_post_meta($post_ID, ‘_wbd_artist_details_grpmembers’, $posted_grpmembers);

    $posted_similar = wbd_posted_group_array($_POST,’wbd_artist_details_similar_’);
    add_post_meta($post_ID, ‘_wbd_artist_details_similar’, $posted_similar, true) or
    update_post_meta($post_ID, ‘_wbd_artist_details_similar’, $posted_similar);

    $posted_links = wbd_posted_group_array($_POST,’wbd_artist_details_links_’);
    add_post_meta($post_ID, ‘_wbd_artist_details_links’, $posted_links, true) or
    update_post_meta($post_ID, ‘_wbd_artist_details_links’, $posted_links);

    $posted_youtubeid = sanitize_text_field( $_POST['wbd_artist_details_youtubeid'] );
    add_post_meta($post_ID, ‘_wbd_artist_details_youtubeid’, $posted_youtubeid, true) or
    update_post_meta($post_ID, ‘_wbd_artist_details_youtubeid’, $posted_youtubeid);



  25. Posted December 24, 2013 at 4:24 pm | Permalink

    This is wonderful, thank you! I’ve used Contact Form 7, your post, and Contact Form 7 Dynamic Text Extension to avoid issues with trying to prefill custom fields in the post edit screen. Now a logged in user can publish from the front end and never have to worry about technical stuff like “Parent ID” for their post. If anyone would like to see the form in action, you can check it out at Thanks again!

    Oh, also, a few edits you might want to consider for your post:
    - Your code shows “>” instead of “>”.
    - I’m using update_post_meta instead of add_post_meta.

One Trackback

  1. [...] modify the Contact Form 7 code itself, which is what I definitely didn’t want to do. I also found this post which talks about using wpcf7_mail_sent action hook to send form data to a custom database. So with [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>