I'm writing a plugin that creates and handles a simple form. This has been my approach sofar, but it's turned out to have some major flaws:

1) On plugin activation, create a blank page for the form at mysite.com/form, and another blank page to process the form at mysite.com/processform. (They need to be separate pages with distinct URLs so that submissions can be tracked via google analytics. Otherwise, I'd just do all this via AJAX. I know, I know... not my decision.)

2) On the "wp" action, check to see what page we're on.

2a) If it's my form page, add a "the_content" filter to render the form (it needs some dynamic hidden elements like a nonce, which is why I didn't just include the form markup when I created the form page originally).

2b) If it's my processform page, add a "the_content" filter to process the POST and render any feedback.

The major problem is with my POST handling. I'm hooking it to the "the_content" filter (because I need it to supply feedback), but this filter is sometimes run multiple times during a page load, causing the POST to be handled multiple times.

I've included what I have below, but I can't help thinking I'm completely on the wrong track with my approach. How would you create and handle a form with your plugin if you needed it to hit a success URL (ie. not via AJAX)?

My code:


    // On activation, create the blank pages
    function my_form_install() {

        $page_markup = '';

        $arr_page_options = array(
            'post_status' => 'publish',
            'post_type' => 'page',
            'post_author' => 1,
            'post_title' => 'Form',
            'post_content' => $page_markup,
            'comment_status' => 'closed'

        $success_page_markup = '';

        $arr_success_page_options = array(
            'post_status' => 'publish',
            'post_type' => 'page',
            'post_author' => 1,
            'post_title' => 'Form Process',
            'post_content' => $success_page_markup,
            'comment_status' => 'closed'


    // On the wp action, check to see if this is one of our pages. If so, add our filters.
    function check_current_page($obj_wp) {

        if(isset($obj_wp->query_vars["pagename"])) {
            $page_name = $obj_wp->query_vars["pagename"];

            switch($page_name) {

                case "form":
                    add_filter('the_content', 'my_render_form');

                case "form-process":
                    add_filter('the_content', 'my_process_form');



    add_action('wp', 'check_current_page');

    // Function to render the form
    function my_render_form($page_markup) {

        $page_markup .= '<form method="post" action="/form-process">
        <input type="text" name="some_input_field" />
        <input type="submit" value="submit" />

        return $page_markup;


    // Function to process the form
    function my_process_form($page_markup) {

        if($_POST) {

            // Do the form processing. This would involve many possible returns, 
            // but I've just included one to simplify thigns.
            $page_markup .= 'Your form has been processed.';


        return $page_markup;



1 Answer 1


That's just a quick feedback: Use a shortcode to insert your form into content. Those are quite flexible. And for the processed form's need to have another URL you can add a rewrite endpoint like /form/processed/ you can check after submission then. That's probably more modular.

In the end that prevents you to deal with the the_content filter as you can deal with anything within the shortcode callback.

It's a rough suggestion only, but probably does the job for you.

  • 1
    Awesome... thanks hakre! This is exactly the kind of answer I was looking for. I didn't even know that the add_rewrite_endpoint() function existed--that'll come in very handy.
    – MathSmath
    Commented Nov 12, 2010 at 17:47

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.