| Confluence no longer sells standalone versions, so legacy users like me may be impacted by this post. In a standalone Confluence instance, you typically have direct access to the server's file system and Confluence's administrative settings. This allows for several methods to inject custom HTML, CSS, and JavaScript. 1. Confluence Administration: Look and Feel > Custom HTMLThis is the recommended and most straightforward method for global injections without modifying core Confluence files directly. The below code is what I added to HEAD - it conditionally load Google Analytics and Adsense scripts when the page URL is not starting as /pages/ <meta name="google-adsense-account" content="<your adsense account info>">
<script>
// External links in new tab
jQuery(document).ready(function() {
jQuery(".external-link").attr("target", "_blank");
});
// Only run if the URL path does NOT start with /pages/
if (!window.location.pathname.startsWith('/pages/')) {
// Google Analytics (gtag.js)
var gtagScript = document.createElement('script');
gtagScript.async = true;
gtagScript.src = 'https://www.googletagmanager.com/gtag/js?id=<your google analytics id>';
document.head.appendChild(gtagScript);
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-1093021-16');
// Google AdSense
var adsenseScript = document.createElement('script');
adsenseScript.async = true;
adsenseScript.src = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=<your google adsense id>';
adsenseScript.crossOrigin = 'anonymous';
document.head.appendChild(adsenseScript);
}
</script>
The above code is actually working when the user loads the page, and I learned that it is not working when Confluence loads pages dynamically with no real page loading, and the below additional code will help you. <script>
function manageTrackingAndAds() {
const isExcludedPath = window.location.pathname.startsWith('/pages/');
// Check if scripts are already there to avoid duplicate injections
const adsenseExists = document.querySelector('script[src*="adsbygoogle.js"]');
if (!isExcludedPath) {
if (!adsenseExists) {
// Inject AdSense only if we are on a valid page and it's not already there
var adsenseScript = document.createElement('script');
adsenseScript.async = true;
adsenseScript.src = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=<your adsense id>';
adsenseScript.crossOrigin = 'anonymous';
document.head.appendChild(adsenseScript);
}
} else {
// If we are on an excluded path, we can't easily "kill" the script,
// but we can hide the ad units via CSS
document.querySelectorAll('.adsbygoogle').forEach(el => el.style.display = 'none');
}
}
// Listen for URL changes in Single Page Apps
window.addEventListener('popstate', manageTrackingAndAds);
// For frameworks that use pushState (like React/Vue/Next.js)
const originalPushState = history.pushState;
history.pushState = function() {
originalPushState.apply(this, arguments);
manageTrackingAndAds();
};
// Run on initial load
manageTrackingAndAds();
</script>
Below is another powerful one that only works for non-signin users. <meta name="google-adsense-account" content="<your Adsense account info>">
<script>
(function() {
// 1. Check if user is NOT logged in
// AJS.params.remoteUser is empty for anonymous users
var isAnonymous = typeof AJS !== 'undefined' && !AJS.params.remoteUser;
if (isAnonymous) {
// --- Logic A: External links in new tab ---
jQuery(document).ready(function() {
jQuery(".external-link").attr("target", "_blank");
});
// --- Logic B: Tracking & Ads Injection ---
function manageTrackingAndAds() {
var path = window.location.pathname;
var isExcludedPath = path.includes('/pages/') || path.includes('.action');
var adsenseExists = document.querySelector('script[src*="adsbygoogle.js"]');
if (!isExcludedPath && !adsenseExists) {
// Google Analytics (gtag.js)
var gtagScript = document.createElement('script');
gtagScript.async = true;
gtagScript.src = 'https://www.googletagmanager.com/gtag/js?id=<your Adsense ID>';
document.head.appendChild(gtagScript);
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-1093021-16');
// Google AdSense
var adsenseScript = document.createElement('script');
adsenseScript.async = true;
adsenseScript.src = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=<yount Adsense ID>';
adsenseScript.crossOrigin = 'anonymous';
document.head.appendChild(adsenseScript);
}
}
// Initialize and handle SPA transitions
window.addEventListener('popstate', manageTrackingAndAds);
var originalPushState = history.pushState;
history.pushState = function() {
originalPushState.apply(this, arguments);
manageTrackingAndAds();
};
manageTrackingAndAds();
}
})();
</script>
|