Adding Posts to a Site’s Front-End Using AJAX

Adding Posts to a Site’s Front-End Using AJAX

Tutorial Details
  • Program: WordPress
  • Difficulty: Intermediate
  • Estimated Completion Time: 45 min

WordPress basically divides itself into two portions, the front end section where people can come and read posts or articles on the site. The other is the WordPress admin section from which one can create posts and pages. This works very well if WordPress is used as a general blogging site. But as WordPress is used for different kinds of sites it sometimes becomes necessary to give the user a way to create posts from the front end of the site without forcing him to go in the WordPress admin section.

In this tutorial we are going to see how to create a widget to let users create posts from the front end. This will help the users of the site to create content.


Step 1 Creating the Plugin

To create a plugin, create a file ajaxpostfromfront.php in your wp-content/plugins/ajaxpostfromfront folder. To create a plugin in WordPress we have to add the plugin header as follows:

/*
Plugin Name: Ajax post from front
Plugin URI: 
Description:Allows to post from front end
Author: Abbas Suterwala
Version: 
Author URI: 
*/

We will also define some named constants for our plugin base URL and the plugin path as follows:

define('APFSURL', WP_PLUGIN_URL."/".dirname( plugin_basename( __FILE__ ) ) );
define('APFPATH', WP_PLUGIN_DIR."/".dirname( plugin_basename( __FILE__ ) ) );

This will help us to use them easily where needed in the plugin. Also create a js folder in your ajaxpostfromfront folder and add a file apf.js in it. So the folder structure of the plugin would be as follows:

We will now enqueue the scripts by hooking on to the action hook ‘wp_enqueue_scripts‘ and enqueue our javascript file and localize it to store the WordPress ajax URL which we will use for our ajax calls.

function apf_enqueuescripts()
{
	wp_enqueue_script('apf', APFSURL.'/js/apf.js', array('jquery'));
	wp_localize_script( 'apf', 'apfajax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
}
add_action('wp_enqueue_scripts', apf_enqueuescripts);

If everything has gone right until now we will be able to see our plugin in the plugin list and we should activate it.


Step 2 Understanding the WordPress Functions to Create a New Post

WordPress has a rich set of APIs or functions which are exposed to perform tasks for plugins. It has functions for all types of tasks like creating a post, creating a page, comments etc. In this plugin we are going to use the WordPress function wp_insert_post.

wp_insert_post takes in an array of the different information required to create a post in WordPress. It takes in different parameters like the post title, post content, post status, etc. It also takes in the array of categories which are to be associated with the post. It also contains some other parameters like post password and post excerpt etc.

For a complete list of parameters you can visit the wp_insert_post page in the WordPress Codex.


Step 3 Creating the UI to Create Post From Front End

Next we are going to create the UI for our post from front end plugin. For this we are going to write the following function:

function apf_post_form()
{
	?>

	<form id="apfform" action="" method="post"enctype="multipart/form-data">

		<div id="apf-text">

			<div id="apf-response" style="background-color:#E6E6FA"></div>

			<strong>Title </strong> <br/>
			<input type="text" id="apftitle" name="apftitle"/><br />
			<br/>

			<strong>Contents </strong> <br/>
			<textarea id="apfcontents" name="apfcontents"  rows="10" cols="20"></textarea><br />
			<br/>

			<a onclick="apfaddpost(apftitle.value,apfcontents.value);" style="cursor: pointer"><b>Create Post</b></a>

		</div>
	</form>

	<?php
}

In the function we will first create a form using the <form> tag. In this we will create a div with the ID apf-response which will update with the message that comes from the AJAX response we will get. Then we have created a text box for the title and a text area for the content of the post.

Next let us create a link called ‘create post’ which calls a javascript function apfaddpost which will make an AJAX call to create the post. We will see the implementation of the AJAX call in the below steps.

In case we call the function apf_post_form in the theme files you will see it as follows. In my theme I have just called it before the main loop.


Step 4 Creating a Widget to Display the UI on Front End

Now we are going to create a widget for our post from front plugin. This widget will display the UI for posting from the front which we created. Following is the code for the widget.

class AjaxPostFromFrontWidget extends WP_Widget {
	function AjaxPostFromFrontWidget() {
		// widget actual processes
		$widget_ops = array('classname' => 'AjaxPostFromFrontWidget', 'description' => 'Lets you create post from front end' );
		$this->WP_Widget('AjaxPostFromFrontWidget','AjaxPostFromFrontWidget', $widget_ops);
	}

	function form($instance) {
		// outputs the options form on admin
		$defaults = array( 'title' => 'Ajax Post From Front' );
		$instance = wp_parse_args( (array) $instance, $defaults );

		?>
		<p>
			<label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php echo 'Title:'; ?></label>
			<input id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo $instance['title']; ?>" class="widefat" />
		</p>
		<?php
	}

	function update($new_instance, $old_instance) {
		// processes widget options to be saved
		$instance = $old_instance;
		$instance['title'] = strip_tags( $new_instance['title'] );

		return $instance;
	}
	
	function widget($args, $instance) {
		// outputs the content of the widget
		extract( $args );

		$title = apply_filters('widget_title', $instance['title'] );
		echo $before_widget;
		if ( $title )
			echo $before_title . $title . $after_title;
		echo '<ul>';
		echo apf_post_form();
		echo '</ul>';
		echo $after_widget;
	}
}

In the constructor we give the class name and the description of the widget. In the form function currently we display only one field that is the title to be displayed for the widget. We update the title field in the update function.

In the widget function we get the title saved in the widget instance and display that. Then we call the function apf_post_form which will display the form that we created in the previous step.

We will register the widget as follows:

function apf_widget_init() {
	// Check for the required API functions
	if ( !function_exists('register_widget') )
		return;

	register_widget('AjaxPostFromFrontWidget');
}
add_action('widgets_init', 'apf_widget_init');

Now we can drag and drop our new widget on the sidebar.

Once the widget is dropped on the side bar you should be able to see the form on the home page in the sidebar as follows:


Step 5 Creating a Post via AJAX From the Front End

Now let’s create a function to handle the AJAX request of creating the post. The function to handle the AJAX request is as follows:

function apf_addpost() {
	$results = '';

	$title = $_POST['apftitle'];
	$content =	$_POST['apfcontents'];

	$post_id = wp_insert_post( array(
		'post_title'		=> $title,
		'post_content'		=> $content,
		'post_status'		=> 'publish',
		'post_author'       => '1'
	) );

	if ( $post_id != 0 )
	{
		$results = '*Post Added';
	}
	else {
		$results = '*Error occurred while adding the post';
	}
	// Return the String
	die($results);
}

In this function we get the values of the title and the content from the $_POST variable. With those values using the wp_insert_post function of WordPress to create the post. The function wp_insert_post returns the newly created post id if succeeded and zero if failed. So using that value we either sent a success or a failure message back from the AJAX.

To register this function with the WordPress AJAX system we will call the following:

// creating Ajax call for WordPress
add_action( 'wp_ajax_nopriv_apf_addpost', 'apf_addpost' );
add_action( 'wp_ajax_apf_addpost', 'apf_addpost' );

Once our AJAX handler is done we just need to make the AJAX request from our javascript code as follows:

function apfaddpost(posttitle,postcontent) {

	jQuery.ajax({

		type: 'POST',

		url: apfajax.ajaxurl,

		data: {
			action: 'apf_addpost',
			apftitle: posttitle,
			apfcontents: postcontent
		},

		success: function(data, textStatus, XMLHttpRequest) {
			var id = '#apf-response';
			jQuery(id).html('');
			jQuery(id).append(data);

			resetvalues();
		},

		error: function(MLHttpRequest, textStatus, errorThrown) {
			alert(errorThrown);
		}

	});
}

function resetvalues() {

	var title = document.getElementById("apftitle");
	title.value = '';

	var content = document.getElementById("apfcontents");
	content.value = '';

}

In the function apfaddpost we just make an AJAX request passing the post title and the post content. Once the response is received we just display the message returned by the AJAX handler in the div apf-response. After that we reset the values in the form.

After clicking on create post the post will be created and the message will be seen as follows:


Step 6 Adding the Option of Letting Only Logged in Users Post

Now we will add the functionality to let the admin choose if they do not want users who are not logged in to create posts.

For this we update the apf_post_form as follows to take an argument $allowNotLoggedInuser. In that case when the user is not logged in, it will not display the form but will display a message to login.

function apf_post_form($allowNotLoggedInuser='yes') {
	if ( $allowNotLoggedInuser == 'no' &&  !is_user_logged_in() ) {
		echo "Please Login to create new post";
		return;
	}
	?>

	<form id="apfform" action="" method="post"enctype="multipart/form-data">

		<div id="apf-text">

			<div id="apf-response" style="background-color:#E6E6FA ;color:blue;"></div>

			<strong>Title </strong> <br/>
			<input type="text" id="apftitle" name="apftitle"/><br />
			<br/>

			<strong>Contents </strong> <br/>
			<textarea id="apfcontents" name="apfcontents"  rows="10" cols="20"></textarea><br />

			<br/>

			<a onclick="apfaddpost(apftitle.value,apfcontents.value);" style="cursor: pointer"><b>Create Post</b></a>

		</div>
	</form>

	<?php
}

We will also update the widget to display one more option in the form function to display a select field asking whether it is allowed for non logged in users to post. We will also update the values in the update function. In the widget function now we read the value which was set in the widget and then pass it to the apf_post_form function.

The updated widget code should look like this:

class AjaxPostFromFrontWidget extends WP_Widget {
	function AjaxPostFromFrontWidget() {
		// widget actual processes
		$widget_ops = array('classname' => 'AjaxPostFromFrontWidget', 'description' => 'Lets you create post from front end' );
		$this->WP_Widget('AjaxPostFromFrontWidget','AjaxPostFromFrontWidget', $widget_ops);
	}

	function form($instance) {
		// outputs the options form on admin
		$defaults = array( 'title' => 'Ajax Post From Front','allow_not_logged_users' => 'no' );
		$instance = wp_parse_args( (array) $instance, $defaults );

		?>
		<p>
			<label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php echo 'Title:'; ?></label>
			<input id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo $instance['title']; ?>" class="widefat" />
		</p>

		<p>
			<label for="<?php echo $this->get_field_id( 'allow_not_logged_users' ); ?>">allow_not_logged_users:</label>
			<select id="<?php echo $this->get_field_id( 'allow_not_logged_users' ); ?>" name="<?php echo $this->get_field_name( 'allow_not_logged_users' ); ?>" class="widefat" style="width:100%;">
				<option <?php if ( 'no' == $instance['allow_not_logged_users'] ) echo 'selected="selected"'; ?>>no</option>
				<option <?php if ( 'yes' == $instance['allow_not_logged_users'] ) echo 'selected="selected"'; ?>>yes</option>
			</select>
		</p>

		<?php
	}

	function update($new_instance, $old_instance) {
		// processes widget options to be saved
		$instance = $old_instance;

		$instance['title'] = strip_tags( $new_instance['title'] );
		$instance['allow_not_logged_users'] = $new_instance['allow_not_logged_users'];
		return $instance;
	}

	function widget($args, $instance) {
		// outputs the content of the widget
		extract( $args );
		$allow_not_logged_users = isset( $instance['allow_not_logged_users'] ) ? $instance['allow_not_logged_users'] : 'no';

		$title = apply_filters('widget_title', $instance['title'] );
		echo $before_widget;
		if ( $title )
			echo $before_title . $title . $after_title;
		echo '<ul>';
		echo apf_post_form($allow_not_logged_users);
		echo '</ul>';
		echo $after_widget;
	}
}

Now from the widget are we can choose the option to whether allow logged in users or no as seen below.

Now in case the option is set to no and someone visits the home page without logging in they will see the following message to login to post.


Step 7 Adding the Option of Adding Categories to Post via Front End Widget

Now we will add the functionality to add categories to the post which we are creating from the front end. To achieve this first we will get the list of all the categories and display them as check boxes on the UI.

For this we add the following code to the function apf_post_form.

<strong>Contents </strong> <br/>
<textarea id="apfcontents" name="apfcontents"  rows="10" cols="20"></textarea><br />

<?php
	$categories = get_categories(array('hide_empty'=> 0));
	foreach ( $categories as $category ) {
		echo "<input type='checkbox' name='apfcategorycheck' id='apfcategorycheck' value='$category->term_id' />";
		echo $category->cat_name;
		echo '<br>';
	}
?>
<br/>

<a onclick="apfaddpost(apftitle.value,apfcontents.value,apfcategorycheck);" style="cursor: pointer"><b>Create Post</b></a>

The above code just gets the list of all categories and displays them as check boxes. That value is passed to our javascript function apfaddpost as an extra parameter.

In the function apfaddpost we get the values which are checked and pass it in the AJAX call as follows:

function apfaddpost ( posttitle,postcontent,postcategory ) {

	var postCatergoryArray = new Array();

	for ( var i=0; i < postcategory.length; i++ ) {
		if ( postcategory[i].checked ) {
			postCatergoryArray[postCatergoryArray.length] = postcategory[i].value;
		}
	}

	jQuery.ajax({

		type: 'POST',

		url: apfajax.ajaxurl,

		data: {
			action: 'apf_addpost',
			apftitle: posttitle,
			apfcontents: postcontent,
			apfcategory:postCatergoryArray
		}
	});

We will need to update the AJAX handler as follows to take the array of ids of the categories and then pass it to the wp_insert_post function , so that the newly created post have the categories appropriately.

function apf_addpost() {
	$results = '';

	$title = $_POST['apftitle'];
	$content =	$_POST['apfcontents'];
	$category = $_POST['apfcategory'];

	$post_id = wp_insert_post( array(
		'post_title'		=> $title,
		'post_content'		=> $content,
		'post_status'		=> 'publish',
		'post_category'		=> $category,
		'post_author'       => '1'
	) );

	if ( $post_id != 0 ) {
		$results = '*Post Added';
	}
	else {
		$results = '*Error occured while adding the post';
	}
	// Return the String
	die($results);
}

Now if we see the widget it will be seen as follows:

And the post created will have those selected categories associated with it as seen below.


Conclusion

WordPress is an extensible platform. We can extend WordPress to add different functionality to so the WordPress platform can be used for different types of sites rather than just blogs. Like in this plugin we have added the functionality of creating posts from the front end, WordPress can be extended in different ways. So happy WordPress coding!

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • Pingback: Adding Posts to a Site’s Front-End Using AJAX | Shadowtek Hosting and Design Solutions

  • http://www.kevinphillips.co.nz Dollar Dad

    Very nice, shame it doesn’t work !!
    Even tried the source code but that doesn’t work either !!
    But that is probably just as well – NO Security around this form !!!
    Using WordPress 3.4

    • Abbas
      Author

      Hi Dollar,

      Please let me know what error does it give.

      Regards,
      Abbas

    • Abbas
      Author

      Hi Dollar,

      Just downloaded the plugin and tried it on WordPress 3.4.
      It worked fine.

      Are you using some particular theme .

      Regards,
      Abbas

  • http://www.wpfix.org Wpfix

    Nice tutorial

  • http://stephenharris.info Stephen Harris

    A nice plug-in but before anyone uses this, it should be pointed out that there are no security checks here – and anyone could create a post whether you allow logged in users to or not.

    Firstly – if you don’t want logged out users to create a post, not displaying the form is not sufficient. Someone could still post data to your admin ajax page and it would be processed and published. (If the option is checked) you also need to check that the person is logged when processing in the ajax callback.

    Secondly – you should uses nonces with the data being sent to check intention. Even with the above check I could trick a logged-in user into publishing content.

    Not displaying a form for logged out users (when the option is checked) is simply for aesthetics and offers no real protection.

    • http://www.ruturaaj.com Ruturaaj

      Excellent points Stephen; your comment shows your experience… so good to have people like you around. In addition to the points you’ve mentioned, sanitizing HTTP POST before you send it to database is equally necessary to avoid sql injection and http request hacks by packet sniffing at user level. Ajax shouldn’t just accept whatever coming to its way through HTTP POST variables.

      Yes, the author has done a good job in simplifying the process and explaining the things in simple words.This tutorial is also good learning point for those who wished to learn how to bridge the gap between JavaScript and PHP using jQuery.

      • http://stephenharris.info Stephen Harris

        Thanks :). I should add though that sanitizing the received data is not necessary here, by using wp_insert_post WordPress will handle inserting the data to the database – and it does this safely. Of course you might want to add in some validation: making sure the content only contains ‘allowed’ HTML tags, but you don’t need to worry about preventing SQL injection here. Cross-site scripting, for instance, is another issue – but sanitising data against this should be down on output. Shameless self promotion, but I recently wrote an article about this on wp.tutplus :)

        • Abbas
          Author

          Thanks Stephen and Ruturaaj for all those valid points.

  • http://www.jonathanlafleur.ca Jonathan Lafleur

    Hi Abbas, that’s a nice tutorial, but I think that there’s a lack regarding post_author, that you can easily set instead of the ‘post_author’ => ’1′ that you’re using.

    According to WordPress Codex ( http://codex.wordpress.org/Function_Reference/wp_insert_post )

    ‘post_author’ => [ ] //The user ID number of the author.

    So all we need is to retreive the ID of the loggued user with this :

    WordPress Codex ( http://codex.wordpress.org/Function_Reference/get_currentuserinfo )
    global $current_user;
    get_currentuserinfo();
    $current_user->ID;

    Thanks for your nice tutorial !

    Oh, one more thing, just to share my idea with others, I would use this to let people submit some articles that they want to be published on my website, all things coming from the from end instead of

    ‘post_status’ => ‘publish’,

    i’ll put them on

    ‘post_status’ => ‘pending’,

    Like this i’m shure that nothings that I haven’t approved first is publish to the front-end.

    We have to protect ourself from automatic bot that spam and things like that ! It’s really important !

  • Ruturaaj

    @Author: May I request you to please share a few words about the “wp_ajax_noprive_{variable}” WordPress Hooks you’ve used here?

    I’ve not tried your code as yet, but I see a few saying it’s not working for them and it just might be because they have upgraded to WordPress 3.4, the latest version of WordPress. Just a guess; I believe you’re the best person to share views on this issue.

    Till this version, we had “wp_ajax_noprive_{$_POST[action]}” and “wp_ajax_{$_POST[action]}” hooks available (wp-admin/admin-ajax.php). But it looks like both these hooks are deprecated in latest version 3.4. In fact, per my information, only two out of “wp_ajax_” family of hooks have managed to get through to this latest version and both are related to Ajax Request. I think this is a good decision by WordPress team by keeping Security at top priority, reasons are already well phrased by Stephen in his comment above. Ajax can be a big trouble.

    So, I please share a few words about these hooks and if these are still valid & available in version 3.4.

    Thanks so much for posting this tutorial.

    • http://stephenharris.info Stephen Harris

      @Ruturaaj – WordPress core has rearranged (and tidied up) it’s handling of ajax calls – but the hooks wp_ajax_{action} and wp_ajax_nopriv_{action} haven’t be deprecated and still work.

      As far as I’m aware, these were, (and still are) the only two hooks with which you can handle ajax requests through WordPress.

      • Ruturaaj

        I see. Thanks for the confirmation. I just checked the code of admin-ajax.php and yes, those actions are there! :-)

  • http://ZenOfWP.com Greg Turner

    Why go to all the trouble of doing this with AJAX when a non-AJAX solution would work just as well?

  • http://www.gleenk.com/ Davide De Maestri

    Interesting post, is there a way to put visual editor into the textarea?

  • http://www.scottfennell.com Scott Fennell

    Awesome! Get my entire DB pwned in 7 easy steps!

    Nonces are for more than just security, too. Have multiple users busily inputting the nonce-less form at approx the same time, and watch the chaos ensue in your DB.

  • Alex Romero

    The ajax module is not working in firefox. Any idea why? I believe it has to do with the HTTP POST, but not sure.

  • Downloadtaky

    Really nice and helpfull tutorial. May I ask a new one about how let users Update Meta Data (custom fields) using ajax?
    I’ll use it for a collaborative board.
    Thank you for your reply.

  • MArtin

    I would like to add option to include tags also,

  • http://www.andreasacca.it/ Andrea

    Great tutorial! Is it possible to add post for a custom post type instead of default “post” post type?

  • http://www.sinavlar.web.tr Bulent Sakarya

    Really great, thanks. How can I add content from an other sites, using content url, like facebook or digg link sharing system…

  • Jacob Kreyenbühl

    Interesting work. It would be great to be able to redirect to the post after creation. Simply adding wp_redirec to apf_addpost() does not work. Any ideas ?

  • Wayne Hesler-Mondore

    Can this be made to allow for adding an expiration date.

  • sanjiv