how can i achieve a front end form with preview option to create custom post based on the input? I want it done without any plugin. A simple example will help a lot.

This is not a ACF question but ACF is having a front end form functionality but does not have preview function.

Is it possible to get the id for form being filled so that it can be passed to

get_preview_post_link( int|WP_Post $post = null, array $query_args = array(), string $preview_link = '' ) 

It tried get the get_the_ID() but it add's the id of page where form is placed. Also the id of the page get generated after form field is generated.

The form is for registered and logged in users. May be if i am able to get a solution to get the id of the post that form generates i will be good position to go further.But the problem is that form generates ID after submission so i can't pass to get_preview_post_link()


  • 1
    worddpress do not have front end forms (well, except for comment) so not sure what are you referring to Aug 18, 2018 at 8:15
  • @MarkKaplun sorry i entered the details incorrectly. i want a form which creates custom post based on entries.
    – user145078
    Aug 18, 2018 at 8:51
  • that sounds more wordpress-y but in that case what is the actual problem you are facing? I assume it is not writing the logic of form itself. So where is the issue here, is it in how to give preview access to unpublished content or something else? Maybe some additional context is also missing (who is using that form, users or anonymous people... what is the context in which the preview should be displayed... whatever you think is applicable and relevant. The more data there is the more likely people can suggest other paths than you thought of. Aug 18, 2018 at 9:10
  • @MarkKaplun The form is for registered and logged in users. May be if i am able to get a solution to get the id of the post that form generates i will be good position to go further.But the problem is that form generates ID after submission so i can't pass to get_preview_post_link()
    – user145078
    Aug 18, 2018 at 10:16

4 Answers 4


There are many ways you could use to reach your goal. Here's one...


  1. Create a shortcode that renders the form.
  2. Create and enqueue a JavaScript file that handles the form submission.
  3. Create PHP function for creating/updating Post/Custom Post.

In your functions.php:

 * @return  string  $html   HTML form.
function shortcode__new_post_form() {
     * @var     WP_User $current_user
    $current_user = $GLOBALS['current_user'];

    ob_start(); ?>
    <form action="" id="form-new-post">
            <legend>NEW AWESOME POST</legend>
            <div class="form-group">
                <input type="text" class="form-control" name="post_title" required/>
            <input type="hidden" name="ID" value=""/>
            <input type="hidden" name="post_author" value="<?php echo $current_user->ID; ?>"/>
            <button type="submit"
        <a href=""
           style="display: none;"
           rel="nofollow">Preview Link</a>
    $html = ob_get_clean();

    return $html;

function script__new_post_form() {
        // Insert here your JavaScript file URL,
        array( 'jquery' ),

            'admin_ajax_url' => admin_url( 'admin-ajax.php' ),

function maybe_insert_new_post() {
     * @var     array $r Initialize response variable.
    $r = array(
        'error'        => '', // Error message.
        'html'         => '', // Any message/HTML you want to output to the logged in user.
        'preview_link' => '', // Preview link URL.
        'post'         => '' // The created/updated post.

     * @link    https://developer.wordpress.org/reference/functions/wp_insert_post/
    $postarr = array(
        'ID'          => '', // If ID stays empty the post will be created.
        'post_author' => '',
        'post_title'  => 'My name is Optimus Prime',
        'post_status' => 'draft',
        'post_type'   => 'post',
        'meta_input'  => array( // Delete this line if you won't use it!
            'your_NON_acf_meta_field_key' => 'your_NON_acf_meta_field_value'

    parse_str( $_POST['form_data'], $form_data );

    $postarr = array_merge( $postarr, $form_data );

     * wp_insert_post can either create posts or update existing ones, if ID is passed!
     * @link    https://developer.wordpress.org/reference/functions/wp_insert_post/
     * @param   array $postarr An array of elements that make up a post to update or insert.
     * @param   bool $wp_error Whether to return a WP_Error on failure.
     * @return  int|WP_Error    The post ID on success. The value 0 or WP_Error on failure.
    $new_post = wp_insert_post(

    // Post was not created/updated, so let's output the error message.
    if ( is_wp_error( $new_post ) ) {
        $r['error'] = $new_post->get_error_message();

        echo json_encode( $r );


    $post_id = $new_post; // Just for reference.

     * To save ACF fields use update_field() function. It doesn't matter if it's text field, repeater field, etc.
     * Make sure the field exists in admin area.
     * Use update_field() as many times as you want.
     * @link    https://www.advancedcustomfields.com/resources/update_field/
    update_field( 'your_acf_meta_key', 'field_value', $post_id );
//  update_field( 'your_acf_meta_key', 'field_value', $post_id );
//  update_field( 'your_acf_meta_key', 'field_value', $post_id );

     * @link    https://developer.wordpress.org/reference/functions/get_preview_post_link/
    $preview_link = get_preview_post_link( $post_id );

    if ( $preview_link ) {
        $r['preview_link'] = $preview_link;

    // Gets post info in array format as it's easier to debug via console if needed.
    $post_array = get_post( $post_id, ARRAY_A );

    if ( $post_array ) {
        $r['post'] = $post_array;

    echo json_encode( $r );


// Ads shortcode so you can use the form anywhere you want.
add_shortcode( 'new_post_form', 'shortcode__new_post_form' );

// Use wp_enqueue_scripts action hook so you can correctly localize the script with admin ajax URL.
add_action( 'wp_enqueue_scripts', 'script__new_post_form' );

// Prefix 'wp_ajax_' is mandatory.
add_action( 'wp_ajax_new_post', 'maybe_insert_new_post' );

Create a JavaScript file and write in it (don't forget to put its URL in your functions.php):

(function ($) {

    var el_form = $('#form-new-post'),
        el_form_submit = $('.submit', el_form);

    // Fires when the form is submitted.
    el_form.on('submit', function (e) {

        el_form_submit.attr('disabled', 'disabled');


    // Ajax request.
    function new_post() {
            url: localized_new_post_form.admin_ajax_url,
            type: 'POST',
            dataType: 'json',
            data: {
                action: 'new_post', // Set action without prefix 'wp_ajax_'.
                form_data: el_form.serialize()
            cache: false
        }).done(function (r) {
            if (r.post !== '' && r.preview_link !== '') {
                $('[name="ID"]', el_form).attr('value', r.post.ID);
                $('.preview-link', el_form)
                    .attr('href', r.preview_link)
                el_form_submit.attr('data-is-updated', 'true');


    // Used to trigger/simulate post submission without user action.
    function trigger_new_post() {

    // Sets interval so the post the can be updated automatically provided that it was already created.
    setInterval(function () {
        if (el_form_submit.attr('data-is-updated') === 'false') {
            return false;

    }, 5000); // Set to 5 seconds.


Now, create a new page and insert the shortcode [new_post_form] in it. Open the page and test your form.

If it works for you, please accept my answer as your solution.

  • Hello thanks. i am getting the following errors with query monitor after adding : Warning preg_match() expects parameter 2 to be string, array given 1 + Toggle button wp-includes/class.wp-scripts.php:314 Core Warning strpos() expects parameter 1 to be string, array given 1 + Toggle button wp-includes/class.wp-scripts.php:314 Core Notice Array to string conversion 1 + Toggle button wp-includes/http.php:659 Core Notice Array to string conversion 1 + Toggle button wp-includes/class.wp-scripts.php:315
    – user145078
    Aug 24, 2018 at 11:09
  • Your error has nothing to with my script which was tested with WP_DEBUG set to true. Please, test it on a fresh WP installation. Aug 24, 2018 at 15:24
  • hello, is it possible to integrate this method with ACF front end form, there is html_after_field=> ' ' i tried it but didn't worked out : advancedcustomfields.com/resources/create-a-front-end-form
    – user145078
    Aug 24, 2018 at 18:28
  • I edited the code so you can save ACF fields correctly. Pay attention to the code, especially the comments. Aug 24, 2018 at 21:15
  • By the way, this mini tutorial - advancedcustomfields.com/resources/create-a-front-end-form - is too simple and too general for your request. Don't realy on it as your only source. Aug 24, 2018 at 21:16

how can i achieve a front end form with preview option to create custom post based on the input? I want it done without any plugin.

without a plugin its not possible unless you're going to do a lot of custom coding which is equivalent to getting a plugin.

The only way you can achieve this without using a plugin is to use the post creation/preview mechanism already available in WP, that is the admin Dashboard. Use a plugin such as Adminimize to fine tune your user's privileges or make a new custom role for them, allowing them to create new posts and review them from the backend dashboard but limiting/removing other dashboard menu items so they only have access to what they need.

  • not sure about adminize, but yes, just give backend access to whatever needed is probably the easier path to follow. Aug 18, 2018 at 10:36
  • i am willing to go to that level. But i need some ideas to make it work. Agree that giving backend access is the easiest way. But want to make the things more convenient and good looking process.
    – user145078
    Aug 18, 2018 at 11:48

You need to create post as draft for preview. You can use this form, function and ajax script for this.

First standart form for new post;

<form method="post" id="new_post_form">
    <input type="text" name="post_title" id="title" />
     * Simple editor for test reasons
        wp_editor( '', 'post_content' );
    <input type="hidden" name="author_id" value="<?php echo get_current_user_id(); ?>" />
    <input type="text" name="security" value="<?php echo wp_create_nonce( "ajax_securiy_nonce" ); ?>">
    <input type="hidden" name="action" value="post_new_thing">
    <input type="submit" id="submit_preview" value="Submit & Preview" />

We will use ajax for posting. So you need an ajax PHP function for this. You can use this function in your functions.php

function add_header_ajax_url(){
    echo '<script type="text/javascript">var ajaxurl = "<?php echo admin_url("admin-ajax.php"); ?>";</script>';

add_action( 'wp_head', 'add_header_ajax_url');

add_action( 'wp_ajax_post_new_thing', 'post_new_thing' );

function post_new_thing() {
     * Post new for post type
    check_ajax_referer( 'ajax_securiy_nonce', 'security' );

    $title     = sanitize_text_field( $_POST['post_title'] );
    $content   = sanitize_text_field( $_POST['post_content'] );
    $author_id = sanitize_text_field( $_POST['author_id'] );

    $args = array(
        'post_title'   => $title,
        'post_content' => $content,
        'post_type'    => 'post',
        'author'       => $author_id,
        'post_status'  => 'draft',

    $posts = wp_insert_post( $args );

    if( is_wp_error( $posts ) ){
        echo json_encode( $posts->get_error_messages() );
    } else {
        if ( !function_exists( 'get_preview_post_link' ) ) { 
            require_once ABSPATH . WPINC . '/link-template.php'; 
        $post_preview = get_preview_post_link($posts);
        echo $post_preview;

This function returns preview link. Also create a post with status as draft. We will force return function to open preview in new tab. Use functions where you want (probably in footer).

<script type="text/javascript">
                type: 'post',
                url : ajaxurl,
                data : $('#new_post_form').serialize(),
                success : function(data){

This codes should work as expected. Comment me if code works or not.

  • Thanks. I tried the your code but it is not working. The forms are being generated . But when i click the button nothing get gets saved any where and the page refreshes to blank form again.
    – user145078
    Aug 18, 2018 at 11:55
  • Ok than there is problem with Ajax function. i am Mobile now. i will check code when return to pc Aug 18, 2018 at 11:57
  • Sorry, we are in qurban vacation. i will fix script tomorrow. Aug 24, 2018 at 21:44

Choose what you think is ideal for the form your after first. Then create it using the the Plugin API of WordPress, or learn the language of those available. Doing a search fo WordPress Forms on Google can be helpful if trying to decide on an API.

There are many, so decide for yourself which is meant for you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.