0

I'm trying to add the ability to redirect a user to a random product/page/post url similar to example.com/page/random which would redirect to example.com/page/oneofmany.

This question is not WooCommerce specific because...

A. This question is about finding a random product/page/post url

B. This question is about 302 redirection from a shortcode to the url in A.

C. It just so happens I'm looking for the product type.

My guess is that I would need to use a custom shortcode ([random_product_page]) which would be replaced with a 302 redirect.

My Questions:

1. How do I retrieve the list of published product/page/post urls and pick one randomly.

2. How should the 302 redirect work?

3. How should this work within function.php, should it even go in function.php.

So far I'm currently trying to add a function to my child theme's function.php to redirect a page with the above short code but have only been able to replace the shortcode with an arbitrary string.

If there is a better way to handle this please let me know. Wordpress development is still pretty new to me.

It has to be a full redirect, example.com/page/random can't just display a random page, the url needs to change so that page view can be tracked.

Solution:

//Custom Code for a Random Endpoints
function random_endpoint() {
        add_rewrite_endpoint( 'random', EP_ROOT );
}
add_action( 'init', 'random_endpoint' );

function random_redirect() {
// If we have accessed our /random/ endpoints.
$post_type = get_query_var( 'random' );
if ( $post_type == '' ) {
    $post_type = [ 'post', 'page', 'product' ];
}
if ( get_query_var( 'random', false ) !== false ) {
    // Get a random post.
    $random_post = get_posts( [
            'numberposts' => 1,
            'post_type'   => $post_type,
            'orderby'     => 'rand',
        ] );

        // If we found one.
        if ( ! empty( $random_post ) ) {
            // Get its URL.
            $url = esc_url_raw( get_the_permalink( $random_post[0] ) );

            // Escape it.
            $url = esc_url_raw( $url );

            // Redirect to it.
            wp_safe_redirect( $url, 302 );
            exit;
        }
    }
}
add_action( 'template_redirect', 'random_redirect' );
4
  • A shortcode is the wrong way to go about this. Shortcodes are for outputting content, not handing things like redirects. Nov 24, 2018 at 4:11
  • When you say random post/page/product do you mean that the random redirect could be to any post/page/product, or will there be seperate links that redirect to each type? Nov 24, 2018 at 4:12
  • @jacobpeattie example.com/product/random should go to a random product page. I'd like to at some point have example.com/page/random and example.com/post/random but product/random is what im working on now.
    – T. Thomas
    Nov 24, 2018 at 6:25
  • 1
    BTW - The reason you don't use a shortcode to do redirects is because in the action stack, shortcodes are rendered AFTER the header is outputted to the browser. So you'll have already outputted data to the browser before your shortcode logic is activated. You need to call the redirect logic before the shortcode, i.e. by using the "init" action hook.
    – John Dee
    Nov 24, 2018 at 17:29

1 Answer 1

1

A shortcode is the wrong way to go about this. Shortcodes are for outputting content, not handing things like redirects.

What we need to do is:

  1. Create a rewrite rule for the /random/ URL that will trigger the redirect.
  2. When the /random/ URL is visited, get a random post/page/product/ and redirect to its URL with a 302.

For step 1 we'll use the rewrite endpoints API to register a /random/ endpoint to the home URL, so that http://example.com/random/ is a URL that we can visit:

function wpse_320084_random_endpoint() {
    add_rewrite_endpoint( 'random', EP_ROOT );
}
add_action( 'init', 'wpse_320084_random_endpoint' );

Make sure to visit Settings > Permalinks to flush the permalinks, or this won't work.

Then we'll hook into template_redirect so that we can redirect the user to a random post if they visit our URL:

function wpse_320084_random_redirect() {
    // If we have accessed our /random/ endpoints.
    if ( get_query_var( 'random', false ) !== false ) {
        // Get a random post.
        $random_post = get_posts( [
            'numberposts' => 1,
            'post_type'   => [ 'post', 'page', 'product' ],
            'orderby'     => 'rand',
        ] );

        // If we found one.
        if ( ! empty( $random_post ) ) {
            // Get its URL.
            $url = esc_url_raw( get_the_permalink( $random_post[0] ) );

            // Escape it.
            $url = esc_url_raw( $url );

            // Redirect to it.
            wp_safe_redirect( $url, 302 );
            exit;
        }
    }
}
add_action( 'template_redirect', 'wpse_320084_random_redirect' );

If you want a separate URL for each post type, then anything passed after an endpoint is accessible with get_query_var():

function wpse_320084_random_redirect() {
    $post_type = get_query_var( 'random' );

    if ( post_type ) {
        $random_post = get_posts( [
            'numberposts' => 1,
            'post_type'   => $post_type,
            'orderby'     => 'rand',
        ] );

        if ( ! empty( $random_post ) ) {
            $url = esc_url_raw( get_the_permalink( $random_post[0] ) );
            $url = esc_url_raw( $url );

            wp_safe_redirect( $url, 302 );
            exit;
        }
    }
}
add_action( 'template_redirect', 'wpse_320084_random_redirect' );

With that code, /random/post/ will load a random post, /random/page/ will load a random page, and /random/product/ will load a random product. Any post type you send after /random/ will redirect to a random post of that type.

5
  • This is what I'm looking for but instead of just example.com/random I need the endpoint to be 'product/random', so example.com/product/random. Anyway to set the endpoint to 'product/random'. I've tried using an escaned forward slash with no luck.
    – T. Thomas
    Nov 24, 2018 at 6:23
  • So you want product/random, page/random and post/random? Nov 24, 2018 at 6:26
  • example.com/product/random should go to a random product page. I'd like to at some point have example.com/page/random and example.com/post/random but product/random is what im working on now.
    – T. Thomas
    Nov 24, 2018 at 6:27
  • 1
    It'll be easier if the url is example.com/random/product if you want me to update my answer with how to do that. Nov 24, 2018 at 6:28
  • Also could I pass along url parameters with this? For example fake.site/random/product/?campaign=google
    – T. Thomas
    Nov 25, 2018 at 4:21

Your Answer

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

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