Content Mirroring System

Full Implementation Guide

Cross-Domain Content Injection for Joomla

Overview

This document provides the complete technical stack required to mirror #sp-component content from a source Joomla site to a mirror site. It handles CORS bypass via PHP and asset path correction via JavaScript

Step 1: The PHP Bridge (Server-Side)

Create a file named grab-content.php in your MIRROR website. This acts as a proxy to fetch the remote HTML. This file should sit in the root of the main directory of that website.

<?php
// This script acts as a bridge to bypass CORS
header('Content-Type: text/html');
echo file_get_contents('[FULL PATH TO SOURCE OF THE PAGE TO DISPLAY');
?>

Step 2: The HTML Placeholder (Client-Side)

Add this container to your Joomla article on the MIRROR where you want the content to load.

<div id="mirrored-content">
    <p>Loading Sixth Form page information... Please wait!</p>
</div>

Step 3: The JavaScript Logic (Client-Side)

Paste this script directly below the placeholder in your article's code view. This could potentially be added to a MODULE to avoid potential edits by end users.

<script>
(function() {
    const targetContainer = document.getElementById('mirrored-content');
    const proxyUrl = 'grab-content.php'; 
    const originalDomain = 'PATH TO MIRROR WEBSITE HOME';
    const customCssUrl = 'PATH TO CUSTOM CSS';

    // Inject CSS
    if (!document.querySelector(`link[href="${customCssUrl}"]`)) {
        const link = document.createElement('link');
        link.rel = 'stylesheet';
        link.href = customCssUrl;
        document.head.appendChild(link);
    }

    fetch(proxyUrl)
        .then(response => response.text())
        .then(html => {
            const parser = new DOMParser();
            const doc = parser.parseFromString(html, 'text/html');
            const content = doc.querySelector('#sp-component');

            if (content) {
                // 1. Fix Paths for images and links
                const assets = content.querySelectorAll('img, a, source');
                assets.forEach(el => {
                    ['src', 'href', 'srcset'].forEach(attr => {
                        const val = el.getAttribute(attr);
                        if (val && !val.startsWith('http') && !val.startsWith('//') && !val.startsWith('#')) {
                            const separator = val.startsWith('/') ? '' : '/';
                            el.setAttribute(attr, originalDomain + separator + val);
                        }
                    });
                });

                // 2. Insert the raw innerHTML to preserve styling/classes
                targetContainer.innerHTML = content.innerHTML;
            } else {
                targetContainer.innerHTML = 'Content area #sp-component not found.';
            }
        })
        .catch(err => {
            targetContainer.innerHTML = 'Unable to load content.';
            console.error(err);
        });
})();
</script>

Critical Note on Joomla Editors

When adding the Step 3 script to a Joomla article, ensure your editor is in "Code" or "Toggle Editor" mode. If you save while in the visual (WYSIWYG) mode, Joomla will strip out the <script> tags for security reasons.