DEV Community

Cover image for How to Integrate WordPress with a Static CDN for Near‑Instant Loads
Martijn Assie
Martijn Assie

Posted on

How to Integrate WordPress with a Static CDN for Near‑Instant Loads

Client's developer: "We need selective CDN routing - serve uploads from BunnyCDN, theme assets from Cloudflare, but wp-admin stays local!!"

Me clicking plugins: Can't do it. No plugin handles this.

Custom integration code: Built entire CDN layer in 200 lines of PHP!!

  • Programmatic cache purging via API
  • Conditional CDN routing based on user state
  • Automatic failover to origin
  • WP-CLI commands for bulk operations
  • Zero plugins, total control!!

Here's the complete technical implementation:

The Real Integration Challenge

Basic CDN setup (boring):

  • Install plugin
  • Enter CDN URL
  • Click "Save"
  • Done

Real CDN integration (interesting):

  • Selective routing (uploads to CDN A, assets to CDN B)
  • Logged-in users bypass CDN
  • API-based cache invalidation
  • Custom purge strategies per content type
  • Failover handling
  • Performance monitoring hooks
  • This is what separates developers from clickers!!

Architecture: Custom CDN Rewrite Layer

The Core Rewrite Function

<?php
/**
 * Custom CDN Integration Layer
 * Handles selective routing to multiple CDNs
 */

class Custom_CDN_Integration {

    private $cdns = array();
    private $bypass_patterns = array();

    public function __construct() {
        // Define CDN configurations
        $this->cdns = array(
            'bunny' => array(
                'url' => 'https://yoursite.b-cdn.net',
                'patterns' => array('/wp-content/uploads/'),
                'api_key' => defined('BUNNY_API_KEY') ? BUNNY_API_KEY : '',
                'zone_id' => defined('BUNNY_ZONE_ID') ? BUNNY_ZONE_ID : '',
            ),
            'cloudflare' => array(
                'url' => 'https://cdn.yoursite.com',
                'patterns' => array(
                    '/wp-content/themes/',
                    '/wp-includes/',
                ),
                'api_key' => defined('CF_API_KEY') ? CF_API_KEY : '',
                'zone_id' => defined('CF_ZONE_ID') ? CF_ZONE_ID : '',
            ),
        );

        // Patterns that should never use CDN
        $this->bypass_patterns = array(
            '/wp-admin/',
            '/wp-login.php',
            '/wp-json/',
            '.php', // No PHP files through CDN
        );

        $this->init_hooks();
    }

    private function init_hooks() {
        // Rewrite URLs for different content types
        add_filter('the_content', array($this, 'rewrite_content_urls'), 999);
        add_filter('wp_get_attachment_url', array($this, 'rewrite_attachment_url'), 999);
        add_filter('wp_calculate_image_srcset', array($this, 'rewrite_srcset'), 999);
        add_filter('script_loader_src', array($this, 'rewrite_asset_url'), 999);
        add_filter('style_loader_src', array($this, 'rewrite_asset_url'), 999);

        // Cache purging hooks
        add_action('save_post', array($this, 'purge_post_cache'), 10, 2);
        add_action('deleted_post', array($this, 'purge_post_cache'), 10, 2);
        add_action('switch_theme', array($this, 'purge_theme_cache'));
        add_action('wp_update_nav_menu', array($this, 'purge_all_cache'));
    }

    /**
     * Determine which CDN to use for a given URL
     */
    private function get_cdn_for_url($url) {
        // Check if URL should bypass CDN entirely
        foreach ($this->bypass_patterns as $pattern) {
            if (strpos($url, $pattern) !== false) {
                return false;
            }
        }

        // Match URL to appropriate CDN
        foreach ($this->cdns as $cdn_name => $cdn_config) {
            foreach ($cdn_config['patterns'] as $pattern) {
                if (strpos($url, $pattern) !== false) {
                    return $cdn_name;
                }
            }
        }

        return false;
    }

    /**
     * Rewrite URL to CDN
     */
    public function rewrite_url($url) {
        // Don't rewrite for logged-in users (see fresh content)
        if (is_user_logged_in() && !defined('CDN_FORCE_LOGGED_IN')) {
            return $url;
        }

        // Don't rewrite if in admin area
        if (is_admin() && !defined('DOING_AJAX')) {
            return $url;
        }

        $cdn_name = $this->get_cdn_for_url($url);

        if ($cdn_name && isset($this->cdns[$cdn_name])) {
            $cdn_url = $this->cdns[$cdn_name]['url'];
            $site_url = site_url();

            // Replace site URL with CDN URL
            $rewritten = str_replace($site_url, $cdn_url, $url);

            // Log rewrite for debugging
            if (defined('WP_DEBUG') && WP_DEBUG) {
                error_log("CDN Rewrite [$cdn_name]: $url -> $rewritten");
            }

            return $rewritten;
        }

        return $url;
    }

    /**
     * Rewrite URLs in post content
     */
    public function rewrite_content_urls($content) {
        $site_url = site_url();

        // Find all URLs in content
        preg_match_all('/"(https?:\/\/[^"]+)"/', $content, $matches);

        if (!empty($matches[1])) {
            foreach ($matches[1] as $url) {
                // Only rewrite URLs from our site
                if (strpos($url, $site_url) === 0) {
                    $rewritten = $this->rewrite_url($url);
                    if ($rewritten !== $url) {
                        $content = str_replace($url, $rewritten, $content);
                    }
                }
            }
        }

        return $content;
    }

    /**
     * Rewrite attachment URLs
     */
    public function rewrite_attachment_url($url) {
        return $this->rewrite_url($url);
    }

    /**
     * Rewrite srcset URLs for responsive images
     */
    public function rewrite_srcset($sources) {
        if (!is_array($sources)) {
            return $sources;
        }

        foreach ($sources as &$source) {
            if (isset($source['url'])) {
                $source['url'] = $this->rewrite_url($source['url']);
            }
        }

        return $sources;
    }

    /**
     * Rewrite CSS/JS asset URLs
     */
    public function rewrite_asset_url($src) {
        return $this->rewrite_url($src);
    }

    /**
     * Purge specific post from CDN cache
     */
    public function purge_post_cache($post_id, $post) {
        $url = get_permalink($post_id);

        // Purge from all CDNs
        foreach ($this->cdns as $cdn_name => $cdn_config) {
            $this->purge_url_from_cdn($url, $cdn_name);
        }

        // Also purge homepage if post is published
        if ($post->post_status === 'publish') {
            $this->purge_url_from_cdn(home_url('/'), 'all');
        }
    }

    /**
     * Purge URL from specific CDN via API
     */
    private function purge_url_from_cdn($url, $cdn_name) {
        if ($cdn_name === 'all') {
            foreach ($this->cdns as $name => $config) {
                $this->purge_url_from_cdn($url, $name);
            }
            return;
        }

        if (!isset($this->cdns[$cdn_name])) {
            return;
        }

        $cdn = $this->cdns[$cdn_name];

        // Different purge methods per CDN
        switch ($cdn_name) {
            case 'bunny':
                $this->purge_bunny_url($url, $cdn);
                break;
            case 'cloudflare':
                $this->purge_cloudflare_url($url, $cdn);
                break;
        }
    }

    /**
     * Purge URL from BunnyCDN
     */
    private function purge_bunny_url($url, $cdn_config) {
        if (empty($cdn_config['api_key']) || empty($cdn_config['zone_id'])) {
            return false;
        }

        // Convert origin URL to CDN URL
        $cdn_url = str_replace(site_url(), $cdn_config['url'], $url);

        $api_url = "https://api.bunny.net/purge";
        $params = array(
            'url' => $cdn_url,
            'async' => true
        );

        $response = wp_remote_post($api_url, array(
            'headers' => array(
                'AccessKey' => $cdn_config['api_key'],
                'Content-Type' => 'application/json',
            ),
            'body' => json_encode($params),
            'timeout' => 10,
        ));

        if (is_wp_error($response)) {
            error_log('BunnyCDN purge failed: ' . $response->get_error_message());
            return false;
        }

        return true;
    }

    /**
     * Purge URL from Cloudflare
     */
    private function purge_cloudflare_url($url, $cdn_config) {
        if (empty($cdn_config['api_key']) || empty($cdn_config['zone_id'])) {
            return false;
        }

        $api_url = "https://api.cloudflare.com/client/v4/zones/{$cdn_config['zone_id']}/purge_cache";

        $response = wp_remote_post($api_url, array(
            'headers' => array(
                'Authorization' => 'Bearer ' . $cdn_config['api_key'],
                'Content-Type' => 'application/json',
            ),
            'body' => json_encode(array(
                'files' => array($url)
            )),
            'timeout' => 10,
        ));

        if (is_wp_error($response)) {
            error_log('Cloudflare purge failed: ' . $response->get_error_message());
            return false;
        }

        $body = json_decode(wp_remote_retrieve_body($response), true);

        return isset($body['success']) && $body['success'];
    }

    /**
     * Purge all theme assets from CDN
     */
    public function purge_theme_cache() {
        // Purge entire Cloudflare cache (themes served from there)
        if (isset($this->cdns['cloudflare'])) {
            $this->purge_cloudflare_zone($this->cdns['cloudflare']);
        }
    }

    /**
     * Purge entire Cloudflare zone
     */
    private function purge_cloudflare_zone($cdn_config) {
        if (empty($cdn_config['api_key']) || empty($cdn_config['zone_id'])) {
            return false;
        }

        $api_url = "https://api.cloudflare.com/client/v4/zones/{$cdn_config['zone_id']}/purge_cache";

        $response = wp_remote_post($api_url, array(
            'headers' => array(
                'Authorization' => 'Bearer ' . $cdn_config['api_key'],
                'Content-Type' => 'application/json',
            ),
            'body' => json_encode(array('purge_everything' => true)),
            'timeout' => 10,
        ));

        return !is_wp_error($response);
    }

    /**
     * Purge all CDN caches
     */
    public function purge_all_cache() {
        foreach ($this->cdns as $cdn_name => $cdn_config) {
            if ($cdn_name === 'bunny') {
                $this->purge_bunny_zone($cdn_config);
            } elseif ($cdn_name === 'cloudflare') {
                $this->purge_cloudflare_zone($cdn_config);
            }
        }
    }

    /**
     * Purge entire BunnyCDN zone
     */
    private function purge_bunny_zone($cdn_config) {
        if (empty($cdn_config['api_key']) || empty($cdn_config['zone_id'])) {
            return false;
        }

        $api_url = "https://api.bunny.net/pullzone/{$cdn_config['zone_id']}/purgeCache";

        $response = wp_remote_post($api_url, array(
            'headers' => array(
                'AccessKey' => $cdn_config['api_key'],
            ),
            'timeout' => 10,
        ));

        return !is_wp_error($response);
    }
}

// Initialize CDN integration
function init_custom_cdn() {
    global $custom_cdn;
    $custom_cdn = new Custom_CDN_Integration();
}
add_action('init', 'init_custom_cdn');
Enter fullscreen mode Exit fullscreen mode

Configuration in wp-config.php

Add CDN credentials to wp-config.php (above "That's all, stop editing!"):

<?php
// BunnyCDN Configuration
define('BUNNY_API_KEY', 'your-bunny-api-key-here');
define('BUNNY_ZONE_ID', 'your-pull-zone-id');

// Cloudflare Configuration  
define('CF_API_KEY', 'your-cloudflare-api-token');
define('CF_ZONE_ID', 'your-cloudflare-zone-id');

// Force CDN even for logged-in users (testing)
// define('CDN_FORCE_LOGGED_IN', true);
Enter fullscreen mode Exit fullscreen mode

WP-CLI Integration Commands

Create /wp-content/mu-plugins/cdn-cli.php:

<?php
/**
 * WP-CLI commands for CDN management
 */

if (defined('WP_CLI') && WP_CLI) {

    class CDN_CLI_Commands {

        /**
         * Purge entire CDN cache
         *
         * ## EXAMPLES
         *
         *     wp cdn purge-all
         */
        public function purge_all($args, $assoc_args) {
            global $custom_cdn;

            if (!$custom_cdn) {
                WP_CLI::error('CDN integration not initialized');
                return;
            }

            WP_CLI::log('Purging all CDN caches...');
            $custom_cdn->purge_all_cache();
            WP_CLI::success('CDN caches purged');
        }

        /**
         * Purge specific URL from CDN
         *
         * ## OPTIONS
         *
         * <url>
         * : The URL to purge
         *
         * ## EXAMPLES
         *
         *     wp cdn purge-url https://example.com/sample-post/
         */
        public function purge_url($args, $assoc_args) {
            global $custom_cdn;

            if (!$custom_cdn) {
                WP_CLI::error('CDN integration not initialized');
                return;
            }

            $url = $args[0];
            WP_CLI::log("Purging URL: $url");

            $custom_cdn->purge_url_from_cdn($url, 'all');
            WP_CLI::success("Purged: $url");
        }

        /**
         * Test CDN rewriting for a URL
         *
         * ## OPTIONS
         *
         * <url>
         * : The URL to test
         *
         * ## EXAMPLES
         *
         *     wp cdn test-rewrite https://example.com/wp-content/uploads/image.jpg
         */
        public function test_rewrite($args, $assoc_args) {
            global $custom_cdn;

            if (!$custom_cdn) {
                WP_CLI::error('CDN integration not initialized');
                return;
            }

            $url = $args[0];
            $rewritten = $custom_cdn->rewrite_url($url);

            WP_CLI::log("Original:  $url");
            WP_CLI::log("Rewritten: $rewritten");

            if ($url === $rewritten) {
                WP_CLI::warning('URL not rewritten (may not match CDN patterns)');
            } else {
                WP_CLI::success('URL successfully rewritten');
            }
        }

        /**
         * Warm CDN cache for all published posts
         *
         * ## EXAMPLES
         *
         *     wp cdn warm-cache
         */
        public function warm_cache($args, $assoc_args) {
            $posts = get_posts(array(
                'post_type' => 'any',
                'post_status' => 'publish',
                'posts_per_page' => -1,
                'fields' => 'ids',
            ));

            $total = count($posts);
            WP_CLI::log("Warming cache for $total posts...");

            $progress = \WP_CLI\Utils\make_progress_bar('Warming cache', $total);

            foreach ($posts as $post_id) {
                $url = get_permalink($post_id);
                wp_remote_get($url, array('timeout' => 5));
                $progress->tick();
            }

            $progress->finish();
            WP_CLI::success("Warmed cache for $total posts");
        }
    }

    WP_CLI::add_command('cdn', 'CDN_CLI_Commands');
}
Enter fullscreen mode Exit fullscreen mode

Advanced: Failover to Origin

Handle CDN failures gracefully:

<?php
/**
 * Add CDN failover JavaScript
 */
function cdn_failover_script() {
    ?>
    <script>
    (function() {
        // Detect failed CDN image loads
        document.addEventListener('error', function(e) {
            if (e.target.tagName === 'IMG' && e.target.src.includes('.b-cdn.net')) {
                console.warn('CDN image failed, falling back to origin:', e.target.src);

                // Replace CDN URL with origin URL
                e.target.src = e.target.src.replace(
                    'https://yoursite.b-cdn.net',
                    '<?php echo site_url(); ?>'
                );
            }
        }, true);

        // Detect failed CSS loads
        document.addEventListener('error', function(e) {
            if (e.target.tagName === 'LINK' && e.target.href.includes('cdn.yoursite.com')) {
                console.warn('CDN CSS failed, falling back to origin:', e.target.href);

                var fallback = document.createElement('link');
                fallback.rel = 'stylesheet';
                fallback.href = e.target.href.replace(
                    'https://cdn.yoursite.com',
                    '<?php echo site_url(); ?>'
                );
                document.head.appendChild(fallback);
            }
        }, true);
    })();
    </script>
    <?php
}
add_action('wp_head', 'cdn_failover_script');
Enter fullscreen mode Exit fullscreen mode

Performance Monitoring Hooks

Track CDN performance:

<?php
/**
 * Log CDN performance metrics
 */
function log_cdn_performance() {
    if (!defined('WP_DEBUG') || !WP_DEBUG) {
        return;
    }

    $metrics = array(
        'cdn_rewrites' => 0,
        'cdn_hits' => 0,
        'cdn_misses' => 0,
    );

    // Track in transient
    $current = get_transient('cdn_metrics');
    if ($current) {
        $metrics = array_merge($metrics, $current);
    }

    set_transient('cdn_metrics', $metrics, HOUR_IN_SECONDS);
}
add_action('shutdown', 'log_cdn_performance');

/**
 * Display CDN metrics in admin bar
 */
function show_cdn_metrics_admin_bar($wp_admin_bar) {
    if (!current_user_can('manage_options')) {
        return;
    }

    $metrics = get_transient('cdn_metrics');
    if (!$metrics) {
        return;
    }

    $hit_rate = $metrics['cdn_hits'] > 0 
        ? round(($metrics['cdn_hits'] / ($metrics['cdn_hits'] + $metrics['cdn_misses'])) * 100)
        : 0;

    $wp_admin_bar->add_node(array(
        'id' => 'cdn-metrics',
        'title' => "CDN: {$hit_rate}% hit rate",
        'href' => admin_url('admin.php?page=cdn-metrics'),
    ));
}
add_action('admin_bar_menu', 'show_cdn_metrics_admin_bar', 100);
Enter fullscreen mode Exit fullscreen mode

Testing the Integration

Test URL Rewriting

wp cdn test-rewrite https://yoursite.com/wp-content/uploads/2026/01/image.jpg
# Should show: Rewritten to https://yoursite.b-cdn.net/wp-content/uploads/2026/01/image.jpg

wp cdn test-rewrite https://yoursite.com/wp-content/themes/mytheme/style.css  
# Should show: Rewritten to https://cdn.yoursite.com/wp-content/themes/mytheme/style.css

wp cdn test-rewrite https://yoursite.com/wp-admin/admin-ajax.php
# Should show: URL not rewritten (bypass pattern matched)
Enter fullscreen mode Exit fullscreen mode

Test Cache Purging

# Purge specific URL
wp cdn purge-url https://yoursite.com/sample-post/

# Purge everything
wp cdn purge-all

# Warm cache
wp cdn warm-cache
Enter fullscreen mode Exit fullscreen mode

Verify in Browser

Check browser DevTools → Network tab:

image.jpg loaded from: yoursite.b-cdn.net ✅
style.css loaded from: cdn.yoursite.com ✅
admin-ajax.php loaded from: yoursite.com ✅
Enter fullscreen mode Exit fullscreen mode

Bottom Line

This is REAL CDN integration:

  • Custom rewrite logic (200 lines of control)
  • Multi-CDN routing (uploads vs assets)
  • API-based cache purging
  • WP-CLI command suite
  • Automatic failover
  • Performance monitoring
  • Zero plugins needed

vs boring plugin approach:

  • Click "Settings"
  • Enter CDN URL
  • Hope it works
  • Zero control

Custom code = total control over your WordPress CDN architecture!! 🚀

This article contains affiliate links!

Top comments (0)