Home / eCommerce / AffiliateWP – Force Query String Format for Affiliate Deep Links
Duplicate Snippet

Embed Snippet on Your Site

AffiliateWP – Force Query String Format for Affiliate Deep Links

Fixes redirect loops caused by AffiliateWP's pretty deep link format (/page/ref/username/) conflicting with WooCommerce or custom permalink plugins. Converts deep links to query string format (/page/?ref=username) both in the Affiliate Area URL generator and for any incoming requests. Does not affect root-level affiliate links.

Code Preview
php
<?php
/**
 * Fix: Force query string format for all affiliate referral URLs.
 *
 * Part 1: Updates the in-memory settings so the portal URL generator
 *         and affwp_get_affiliate_referral_url() both produce ?ref=value
 *         format instead of /ref/value/ format. No database change.
 *
 * Part 2: Converts any incoming pretty deep link (/page/ref/value/) to
 *         query string format (/page/?ref=value) via 301 redirect.
 *         Fixes redirect loops for links already in the wild.
 *         Skips root-level pretty URLs (/?ref=value works fine).
 */
// Part 1: Force query string format in URL generation.
add_action( 'plugins_loaded', function() {
    affiliate_wp()->settings->set( array( 'referral_pretty_urls' => false ) );
}, 20 ); // Priority 20 runs after AffiliateWP initializes at priority 10.
// Part 2: Redirect incoming pretty deep links to query string format.
add_action( 'init', function() {
    if ( is_admin() ) {
        return;
    }
    $referral_var = affiliate_wp()->tracking->get_referral_var();
    $request_uri  = isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : '';
    // Match URLs like /some/path/ref/username/ or /some/path/ref/username/?foo=bar
    $pattern = '#^(/[^?]+)/' . preg_quote( $referral_var, '#' ) . '/([^/?]+)/?(\?.*)?$#';
    if ( ! preg_match( $pattern, $request_uri, $matches ) ) {
        return;
    }
    $path         = trailingslashit( $matches[1] );
    $affiliate    = sanitize_text_field( $matches[2] );
    $query_string = ! empty( $matches[3] ) ? ltrim( $matches[3], '?' ) : '';
    // Skip root-level pretty URLs e.g. domain.com/ref/username/ -- those work fine.
    if ( '/' === $path ) {
        return;
    }
    // Build the query string version of the URL.
    $redirect = add_query_arg( $referral_var, $affiliate, home_url( $path ) );
    if ( $query_string ) {
        $redirect .= '&' . $query_string;
    }
    // Use header() directly to bypass AffiliateWP's wp_redirect filter,
    // which would re-append /ref/username/ and recreate the loop.
    header( 'Location: ' . esc_url_raw( $redirect ), true, 301 );
    exit;
}, 1 ); // Priority 1 runs before AffiliateWP's fallback tracking at priority -9999... 
        // actually at priority 1 this fires before AffiliateWP's template_redirect,
        // but we're on 'init' so it's earlier in the request lifecycle entirely.

Comments

Add a Comment