12% off of LTD using this coupon: TWELVEPERCENTOFF. Promo ends on 2 Dec midnight UTC.
Published on Oct 18, 2020

How to build an automatic redirect loading screen using Oxygen and ACF


This tutorial is was originally published by Alex Tester at smoothwebsites.net, and is shared here at his request.

I work on a number of different affiliate websites, and as anyone who does the same will tell you, getting your affiliate links right is crucial.

Jump to tutorial

What Are Affiliate Links?

For the uninitiated: affiliate websites link out to certain other sites in the hope of gaining them a customer, which then leads to a commission for us. Usually this link is included in a top 10 list, or a review, but it can appear anywhere.

The other website provides you a specially generated ‘tracker link’ containing your particular affiliate code. When someone then clicks on it and arrives on the other site, they know that the traffic came from you and can compensate you appropriately.

The Problem

Unfortunately, these links are often quite.. ugly. A typical example:


This looks pretty spammy to the average user.

Of course you can wrap it in a text link or a button, but your user will still see this URL if they hover over the link, and that might be enough to put them off.

In affiliation, every link counts – which is why most affiliate websites disguise their tracker links to look something like this:


Much better!

The Solution

Redirections plugins are commonly used for this – they are ideal if you need a nice simple GUI where you can put in the desired ‘pretty’ link and its final destination. 301 Redirection, Pretty Links, Rank Math and plenty more options exist.

The problem is that once you surpass 50 links, it starts to get unwieldy. Scalability becomes a problem. I’m all about that, so I set about finding a way of storing this link inside the data of the page it related to. And here it is.

How To Code Your Own Redirects

All you need to follow this tutorial is Advanced Custom Fields, plus the excellent and free Code Snippets plugin. This allows you to add snippets of code which translate into added functionality. Adding the code to functions.php is also an option but I prefer Code Snippets because:

  • It works with Oxygen Builder which disables theme files including functions.php.
  • It’s cleaner, and has a very nice interface for activating/deactivating snippets. It’s like a mini-plugins plugin.

On with the tutorial..

Step 1: Set up link field and create post

  1. On ACF, add a new Field Group called ‘Affiliate Links’.
  2. In the Field Group add a single text field called ‘Tracker Link’.
  3. Set the Field Group to show only on Post Type ‘Posts’. If you have a custom post type set up for the products/sites you review, use that.
  1. Save the Field Group, and create a new Post called ‘Test Redirect’.
  2. You should be able to see the newly created ‘Tracker Link’ field. Enter “https://www.amazon.com” in the field, and save the Post.

Step 2: Create the affiliate link custom post type

  1. Custom post types can be made using a tool like Pods, ACF Extended, or CPTUI. In this case though, we’ll code it manually.
  2. Go to Snippets, and click ‘Add New’.
  3. Give it the title “[CPT] Affiliate Links”, and paste the following code snippet:
// Register Affiliate Links Custom Post Type
function affiliate_links_post_type() {

	$labels = array(
		'name'                  => _x( 'Affiliate Links', 'Post Type General Name', 'text_domain' ),
		'singular_name'         => _x( 'Affiliate Link', 'Post Type Singular Name', 'text_domain' ),
		'menu_name'             => __( 'Affiliate Links', 'text_domain' ),
		'name_admin_bar'        => __( 'Affiliate Link', 'text_domain' ),
		'archives'              => __( 'Item Archives', 'text_domain' ),
		'attributes'            => __( 'Item Attributes', 'text_domain' ),
		'parent_item_colon'     => __( 'Parent Affiliate Link:', 'text_domain' ),
		'all_items'             => __( 'All Affiliate Links', 'text_domain' ),
		'add_new_item'          => __( 'Add New Affiliate Link', 'text_domain' ),
		'add_new'               => __( 'Add Affiliate Link', 'text_domain' ),
		'new_item'              => __( 'New Item', 'text_domain' ),
		'edit_item'             => __( 'Edit Affiliate Link', 'text_domain' ),
		'update_item'           => __( 'Update Affiliate Link', 'text_domain' ),
		'view_item'             => __( 'View Affiliate Link', 'text_domain' ),
		'view_items'            => __( 'View Items', 'text_domain' ),
		'search_items'          => __( 'Search affiliate links', 'text_domain' ),
		'not_found'             => __( 'No affiliate links found', 'text_domain' ),
		'not_found_in_trash'    => __( 'No affiliate links found in Trash', 'text_domain' ),
		'featured_image'        => __( 'Featured Image', 'text_domain' ),
		'set_featured_image'    => __( 'Set featured image', 'text_domain' ),
		'remove_featured_image' => __( 'Remove featured image', 'text_domain' ),
		'use_featured_image'    => __( 'Use as featured image', 'text_domain' ),
		'insert_into_item'      => __( 'Insert into item', 'text_domain' ),
		'uploaded_to_this_item' => __( 'Uploaded to this item', 'text_domain' ),
		'items_list'            => __( 'Items list', 'text_domain' ),
		'items_list_navigation' => __( 'Items list navigation', 'text_domain' ),
		'filter_items_list'     => __( 'Filter items list', 'text_domain' ),
	$args = array(
		'label'                 => __( 'Affiliate Link', 'text_domain' ),
		'description'           => __( 'Affiliate Links.', 'text_domain' ),
		'labels'                => $labels,
		'supports'              => array( 'title', 'revisions', ),
		'taxonomies'            => false,
		'hierarchical'          => false,
		'public'                => true,
		'show_ui'               => true,
		'show_in_menu'          => true,
		'menu_position'         => 8,
		'menu_icon'             => 'dashicons-media-text',
		'show_in_admin_bar'     => true,
		'show_in_nav_menus'     => true,
		'can_export'            => true,
		'has_archive'           => false,
		'rewrite'		=> array('slug' => 'go'),
		'exclude_from_search'   => true,
		'publicly_queryable'    => true,
		'capability_type'       => 'page',
	register_post_type( 'affiliate_link', $args );

add_action( 'init', 'affiliate_links_post_type', 0 );
  1. Click ‘Save and Activate’, and you should see a shiny new post type called ‘Affiliate Links’ in your WordPress sidebar.
  2. Go to Settings > Permalinks, and re-save to make sure your new CPT is registered.
  3. Go to ‘Affiliate Links’, and Add New. Give the new post a title of ‘Test Redirect’. Important: it is critical that the slug of the page (in this case: test-redirect) is the same as that of the Post you made earlier.
  1. Optional – you may wish to use your SEO plugin of choice to noindex all Affiliate Link pages, or block the path /go/ in your robots.txt.

Step 3: Setting up the redirect

  1. Navigate back to Oxygen > Templates, and click Add New.
  2. Set the template to apply on Singular > Affiliate Links, and inherit from none.
  3. Save and click Edit with Oxygen.
  4. When the template loads, create a code block element and give it a class of loading-container.
  5. Add the following code to the relevant parts of the code block:



// Get ID of current Affiliate Link page
$post_id = get_the_ID();

// Get slug of Affiliate Link page
$slug = get_post_field( 'post_name', $post_id );

// Get related Post with the same slug
$related_post = get_page_by_path( $slug, OBJECT, 'post' );

// Get ID of Post
$review_id = $related_post->ID;

// Get title of Post
$destination_title = get_the_title( $review_id );

// Get link from Post
$destination = get_field('tracker_link', $review_id);

// Get thumbnail from Post
$destination_logo = get_post_thumbnail_id($review_id);

// If no related review go to this URL
$fallback = "/";


<?php if($related_post) { ?>

<div class="loading-logo-container">
  <?php echo wp_get_attachment_image( $destination_logo, 'medium', false, array ('alt' => get_the_title(), 'class' => "loading-logo") ); ?>

<div class="loading-message">
	Sit tight, we're taking you to <?php echo $destination_title; ?>...

<div class="loading-message">
	Not working? <a href="<?php echo $destination; ?>">Click here</a>!

<div class="thanks-message">
  Thanks for visiting <?php bloginfo( 'name' ); ?>!

header( "refresh:1;url=$destination" );

<?php } else {
  header( "refresh:0;url=$fallback" );


.loading-container {
  width: 100%;
  min-height: 100vh;
  padding-top: 20px;
  padding-left: 20px;
  padding-right: 20px;
  padding-bottom: 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;

@-webkit-keyframes loading {
  0% {
    -webkit-transform: rotateY(0deg);
    transform: rotateY(0deg);
  100% {
    -webkit-transform: rotateY(360deg);
    transform: rotateY(360deg);

@keyframes loading {
  0% {
    -webkit-transform: rotateY(0deg);
    transform: rotateY(0deg);
  100% {
    -webkit-transform: rotateY(360deg);
    transform: rotateY(360deg);

.loading-logo-container {
  background-color: #ffffff;
  padding: 10px;
  border-radius: 6px;
  box-shadow: 0 0 40px -10px #bbb;
  margin-bottom: 20px;
  -webkit-animation: 1.8s loading infinite;
  animation: 1.8s loading infinite;

.loading-rating {
  font-weight: 700;
  font-size: 2.5em;
  margin-bottom: 20px;

.loading-message {
  font-size: 1.5em;
  margin-bottom: 40px;

.loading-message a {
  font-size: inherit;
  font-weight: 700;

.thanks-message {
  font-size: 2em;
  1. Save the template and click Back to WP > Admin
  2. Go to your Affiliate Links and click View on the Test Redirect post you made earlier. You should see loading screen for one second before being redirected.

That’s it! End result: cleaner and more manageable data architecture, one less plugin, and more efficiency!

See it in action: https://smoothwebsites.net/go/cloudways

Questions and Answers

Is this a 301 redirect?

The SEOs in particular may want the answer to this one, as 301 is the generally-accepted HTML status code to use for affiliate link redirects.

Technically, this method is not a 301 redirect. What it does is refresh the page after a set period of time (one second, in this example), and by setting the URL of a different page in the refresh parameters, it gives the same user experience as a redirect. In fact, Screaming Frog crawls it as a 301, which suggests that other crawlers may do the same.

Although this is not the done thing really, as an SEO who doesn’t really believe in too many hard-and-fast rules, I think the solution works.

Usually you will be doing all of / some combination of the following:

  • noindexing your /go/ links,
  • nofollowing them,
  • and blocking them in robots.txt.

Which means that Google isn’t going to be looking at them, so as long as the user experience is the same, I say why does it matter what the status code is? Answers on a postcard please 🙂

Can I use a custom post type instead of Posts?

Yes. The key is in this segment of the code block:

// Get related Post with the same slug
$related_post = get_page_by_path( $slug, OBJECT, 'post' );

Simply replace ‘post’ with the name of your CPT, for example:

// Get related Review with the same slug
$related_post = get_page_by_path( $slug, OBJECT, 'review' );

I hope this helps some people. My name is Alex, I’m a WordPress designer/developer with a background in content writing and SEO – learning more and more each day.

Big thanks to Sridhar for republishing this tutorial here, and for giving me the grounding in PHP that made it possible. The original tutorial can be found here.