/** * This script downloads Google Tag Manager script, compresses it, and serves it locally * This helps with the "Enable text compression" and "Minify JavaScript" issues */ const fs = require('fs'); const path = require('path'); const https = require('https'); const zlib = require('zlib'); const { execSync } = require('child_process'); // Configuration const GTM_ID = 'G-XXXXXXXX'; // Replace with your actual GTM ID const OUTPUT_DIR = path.join(__dirname, '../public/scripts'); const OUTPUT_FILE = path.join(OUTPUT_DIR, 'gtm.js'); const OUTPUT_FILE_MIN = path.join(OUTPUT_DIR, 'gtm.min.js'); const OUTPUT_FILE_GZIP = path.join(OUTPUT_DIR, 'gtm.min.js.gz'); const OUTPUT_FILE_BR = path.join(OUTPUT_DIR, 'gtm.min.js.br'); // Ensure the output directory exists if (!fs.existsSync(OUTPUT_DIR)) { fs.mkdirSync(OUTPUT_DIR, { recursive: true }); } // Function to download the GTM script function downloadGTMScript() { return new Promise((resolve, reject) => { console.log('Downloading Google Tag Manager script...'); const url = `https://www.googletagmanager.com/gtag/js?id=${GTM_ID}`; https.get(url, (response) => { if (response.statusCode !== 200) { reject(new Error(`Failed to download script. Status code: ${response.statusCode}`)); return; } let data = ''; response.on('data', (chunk) => { data += chunk; }); response.on('end', () => { fs.writeFileSync(OUTPUT_FILE, data); console.log(`Downloaded script to ${OUTPUT_FILE}`); resolve(data); }); }).on('error', (err) => { reject(err); }); }); } // Function to minify the script using Terser function minifyScript(script) { try { console.log('Minifying script...'); // Check if terser is available try { execSync('npx terser --version', { stdio: 'ignore' }); } catch (err) { console.log('Terser not found. Installing...'); execSync('npm install --no-save terser', { stdio: 'inherit' }); } // Minify script with terser const minified = execSync( `npx terser --compress --mangle --output "${OUTPUT_FILE_MIN}" "${OUTPUT_FILE}"`, { encoding: 'utf8' } ); console.log(`Minified script saved to ${OUTPUT_FILE_MIN}`); // Read the minified file const minifiedContent = fs.readFileSync(OUTPUT_FILE_MIN, 'utf8'); return minifiedContent; } catch (err) { console.error('Error minifying script:', err); // Fall back to original script if minification fails return script; } } // Function to compress the script with gzip function compressWithGzip(script) { console.log('Compressing with gzip...'); const compressed = zlib.gzipSync(script, { level: 9 }); fs.writeFileSync(OUTPUT_FILE_GZIP, compressed); console.log(`Gzip compressed script saved to ${OUTPUT_FILE_GZIP}`); } // Function to compress the script with Brotli function compressWithBrotli(script) { console.log('Compressing with brotli...'); const compressed = zlib.brotliCompressSync(script, { params: { [zlib.constants.BROTLI_PARAM_QUALITY]: 11, }, }); fs.writeFileSync(OUTPUT_FILE_BR, compressed); console.log(`Brotli compressed script saved to ${OUTPUT_FILE_BR}`); } // Generate a helper script to include in your HTML function generateHelperScript() { const helperContent = ` /** * Helper script to load the Google Tag Manager script with proper compression * Include this script in your Next.js app to load GTM with compression support */ export function loadGTM(id = '${GTM_ID}') { // Create a script element to load our compressed GTM script const script = document.createElement('script'); // Try to use the local compressed version first const supportsCompression = 'HTMLScriptElement' in window; // If the browser supports modern features, use our compressed local version if (supportsCompression) { script.src = '/scripts/gtm.min.js'; } else { // Fallback to the original Google Tag Manager script script.src = \`https://www.googletagmanager.com/gtag/js?id=\${id}\`; } script.async = true; document.head.appendChild(script); // Initialize GTM window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', id); } `; const helperPath = path.join(__dirname, '../utils/gtm.js'); fs.writeFileSync(helperPath, helperContent); console.log(`Helper script saved to ${helperPath}`); } // Main function async function main() { try { const script = await downloadGTMScript(); const minified = minifyScript(script); compressWithGzip(minified); compressWithBrotli(minified); generateHelperScript(); console.log('\nAll done! To use the compressed GTM script:'); console.log('1. Update your Next.js configuration to serve .gz and .br files with correct Content-Encoding headers'); console.log('2. Import the loadGTM function from utils/gtm.js and use it in your layout component'); console.log('3. Run this script periodically to keep your GTM script up to date'); } catch (err) { console.error('Error:', err); process.exit(1); } } main();