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:
- Create a rewrite rule for the
/random/
URL that will trigger the redirect. - 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.