Setcookie works on admin but not front end

I have a simple function to set a cookie to the value of whatever parameter is attached. For example, if I visit http://example.com/?devsource=http://dev.example.com/ it should set the value of the devsourceurl cookie to http://dev.example.com/

This function works great in the WordPress admin, but I cannot get it to work on the front end. I even tried checking to see if headers were already sent at the init action and they weren’t. Any ideas what could cause this? Here’s the code:

Read More
function set_devsource_cookie() {
    if ($_GET['devsource']) {
        $value = $_GET['devsource'];
        setcookie("devsourceurl", $value, time()+3600, COOKIEPATH, COOKIE_DOMAIN, false );
        echo $_COOKIE["devsourceurl"]; /* echo cookie if set */
    }
}
add_action('init', 'set_devsource_cookie', 0);

Thanks for any help!

Related posts

Leave a Reply

1 comment

  1. Some things non-WordPress specific regarding cookies:

    • set cookie fails if some output has been done in the page
    • you can’t access to coockie value in the same request you set it (as @Milo pointed out in a comment to OP)

    Another general rule is better to use filter_input or filter_intput_array instead of direct accessing to super globals like $_GET or $_COOKIE.

    As a direct consequence of the first thing I said (set cookie fails if some output) is better se cookie as soon as possible, and in WordPress even if ‘init’ is quite early, there are hooks that are earlier, if you are writing a plugin you can use 'plugin_loaded' if you are developing a theme you can use 'after_setup_theme'.

    function set_devsource_cookie() {
      global $devsource;
      $get = filter_input( INPUT_GET, 'devsource', FILTER_SANITIZE_STRING );
      if ( ! empty( $get ) ) {
        $devsource = $get;
        setcookie( 'devsourceurl', $devsource, time() + 3600, COOKIEPATH, COOKIE_DOMAIN, false );
      } else {
        $cookie = filter_input( INPUT_COOKIE, 'devsourceurl', FILTER_SANITIZE_STRING );
        if ( ! empty( $cookie ) ) {
          $devsource = $cookie;
        }
      }
      // debug
      // die( '---------------------');
      // uncommenting previous line, the dashes must be the the absolutely first line
      // if there's something first, even an empty line the cookie can't be set!
    }
    
    // prefer this on plugin
    // add_action( 'plugins_loaded', 'set_devsource_cookie', 0 );
    add_action( 'after_setup_theme', 'set_devsource_cookie', 0 );
    

    Now testing if the value was set on wp footer (just as example):

    function test_devsource_cookie() {
      global $devsource;
      echo 'Devsource is: ';
      echo ! empty( $devsource ) ? $devsource : 'not set.';
      echo '<br>Set again to random uri: ';
      $random = strtolower( wp_generate_password( 6, FALSE, FALSE ) );
      $url = add_query_arg( array('devsource' => "http://dev.{$random}.com/" ) );
      echo '<a href="' . $url . '">Set</a>';
    }
    
    add_action( 'wp_footer', 'test_devsource_cookie' );
    

    If this code does’t work, likely something (a plugin, the theme) is output something on the page before the code runs, sometimes even an empty line before the <?php can make fail a cookie to be set, see the commented lines in my set_devsource_cookie function.

    If you see some output on the page, disable all plugins and use a default theme, put my code in a plugin and only activate it: the code should work.

    After that re-enable your theme and plugins one by one to find the culprit.

    Last tip: when you need to pass urls as param to the url be sure to use urlencode, jus I do on my test_devsource_cookie function.