captaincore/lib/remote-scripts/deploy-fathom
2026-04-06 19:05:35 -04:00

129 lines
11 KiB
Bash

#!/usr/bin/env bash
#
# Deploy Fathom
#
# `deploy-fathom --tracker=<tracker-domain> --tracker_url=<tracker-url> --id=<site-id> --branding_author=<captaincore_branding_author> --branding_author_uri=<captaincore_branding_author_uri> --branding_slug=<captaincore_branding_slug>`
#
# Loop through arguments and separate regular arguments from flags
for arg in "$@"; do
# Add to arguments array. (Does not starts with "--")
if [[ $arg != --* ]]; then
count=1+${#arguments[*]}
arguments[$count]=$arg
continue
fi
# Remove leading "--"
flag_name=$( echo $arg | cut -c 3- )
# Add to flags array
count=1+${#flags[*]}
flags[$count]=$arg
# Process flags without data (Assign to variable)
if [[ $arg != *"="* ]]; then
flag_name=${flag_name//-/_}
declare "$flag_name"=true
fi
# Process flags with data (Assign to variable)
if [[ $arg == *"="* ]]; then
flag_value=$( echo $flag_name | perl -n -e '/.+?=(.+)/&& print $1' ) # extract value
flag_name=$( echo $flag_name | perl -n -e '/(.+?)=.+/&& print $1' ) # extract name
flag_name=${flag_name/-/_}
# Remove first and last quote if found
flag_value="${flag_value%\"}"
flag_value="${flag_value#\"}"
declare "$flag_name"="$flag_value"
continue
fi
done
if [[ "$wp_content" == "" ]]; then
wp_content="wp-content"
fi
fathom_arguments=$( echo $fathom_arguments | base64 --decode )
while read -r line; do
declare "$line"
done <<< "$fathom_arguments"
# Remove legacy trackers
if ls $wp_content/mu-plugins/${branding_slug}-*tracker.js &>/dev/null; then
echo "Removing existing trackers"
rm $wp_content/mu-plugins/${branding_slug}-*tracker.js
rm -f $wp_content/mu-plugins/${branding_slug}-*analytics.js
fi
for legacy in "${branding_slug}-stats.php" "${branding_slug}-tracker.php" "${branding_slug}-tracker.js"; do
if [ -f "$wp_content/mu-plugins/$legacy" ]; then
echo "Removing legacy tracker '$wp_content/mu-plugins/$legacy'"
rm "$wp_content/mu-plugins/$legacy"
fi
done
# Store Fathom tracking IDs in WordPress option (read at runtime, not embedded in file)
echo "Setting captaincore_fathom option"
if wp core is-installed --network --skip-themes --skip-plugins --skip-packages 2>/dev/null; then
wp site option update captaincore_fathom "$id" --format=json --skip-themes --skip-plugins --skip-packages 2>/dev/null
else
wp option update captaincore_fathom "$id" --format=json --skip-themes --skip-plugins --skip-packages 2>/dev/null
fi
# Generate universal mu-plugin (static codebase — reads tracking IDs from wp_options)
mkdir -p "$wp_content/mu-plugins/"
echo "Generating '$wp_content/mu-plugins/captaincore-analytics.php'"
cat > "$wp_content/mu-plugins/captaincore-analytics.php" << 'PHPEOF'
<?php
/**
* Plugin Name: CaptainCore Analytics
* Plugin URI: https://captaincore.io/analytics
* Description: Analytics powered by Fathom Analytics bundled with CaptainCore
* Version: 1.5.0
* Author: CaptainCore
* Author URI: https://captaincore.io/analytics
* Text Domain: captaincore-analytics
*/
function captaincore_fathom_analytics_snippet() {
$fathom = get_site_option( 'captaincore_fathom' );
if ( empty( $fathom ) ) {
return;
}
// Multisite: match current domain to tracking code
if ( is_array( $fathom ) && count( $fathom ) > 1 && function_exists( 'get_blog_details' ) ) {
$current_domain = get_blog_details()->domain;
$site_id = '';
foreach ( $fathom as $entry ) {
if ( isset( $entry['domain'] ) && $entry['domain'] === $current_domain ) {
$site_id = $entry['code'];
break;
}
}
} else {
// Single site: use first entry
$entry = is_array( $fathom ) ? ( $fathom[0] ?? [] ) : [];
$site_id = $entry['code'] ?? '';
}
if ( ! empty( $site_id ) ) {
echo '<script src="' . esc_url( content_url( '/mu-plugins/captaincore-analytics.js' ) )
. '" data-site="' . esc_attr( $site_id ) . '" defer></script>' . "\n";
}
}
add_action( 'wp_head', 'captaincore_fathom_analytics_snippet', 50 );
PHPEOF
echo "Generating '$wp_content/mu-plugins/captaincore-analytics.js'"
cat > "$wp_content/mu-plugins/captaincore-analytics.js" << 'JSEOF'
window.fathom_captaincore=(()=>{var fathomScript=document.currentScript||document.querySelector('script[src*="script.js"][site]')||document.querySelector("script[data-site]")||document.querySelector("script[site]"),siteId=fathomScript.getAttribute("data-site")||fathomScript.getAttribute("site"),honorDNT=!1,auto=!0,canonical=!0,excludedDomains=[],allowedDomains=[],pageStart=("true"===(fathomScript.getAttribute("data-honor-dnt")||fathomScript.getAttribute("honor-dnt"))&&(honorDNT="doNotTrack"in navigator&&"1"===navigator.doNotTrack),"false"===(fathomScript.getAttribute("data-auto")||fathomScript.getAttribute("auto"))&&(auto=!1),"false"===(fathomScript.getAttribute("data-canonical")||fathomScript.getAttribute("canonical"))&&(canonical=!1),(fathomScript.getAttribute("data-excluded-domains")||fathomScript.getAttribute("excluded-domains"))&&(excludedDomains=(fathomScript.getAttribute("data-excluded-domains")||fathomScript.getAttribute("excluded-domains")).split(",")),fathomScript.getAttribute("data-included-domains")||fathomScript.getAttribute("included-domains")?allowedDomains=(fathomScript.getAttribute("data-included-domains")||fathomScript.getAttribute("included-domains")).split(","):(fathomScript.getAttribute("data-allowed-domains")||fathomScript.getAttribute("allowed-domains"))&&(allowedDomains=(fathomScript.getAttribute("data-allowed-domains")||fathomScript.getAttribute("allowed-domains")).split(",")),null),currentHostname=null,currentPathname=null,currentSiteId=null,currentQueryString=null;function sendDeparturePing(){var duration;pageStart&&trackingEnabled()&&(duration=Math.min(Math.round((Date.now()-pageStart)/1e3),1800),pageStart=null,duration<=0||navigator.sendBeacon(trackerUrl+encodeParameters({dp:1,sid:currentSiteId||siteId,h:currentHostname,p:currentPathname,qs:currentQueryString,d:duration})))}function trackPageview(){sendDeparturePing(),window.fathom_captaincore.trackPageview()}function spaHistory(){var pushState;void 0!==history&&(pushState=history.pushState,history.pushState=function(){var ret=pushState.apply(history,arguments);return window.dispatchEvent(new Event("pushstate")),window.dispatchEvent(new Event("locationchangefathom")),ret},window.addEventListener("popstate",function(){window.dispatchEvent(new Event("locationchangefathom"))}),window.addEventListener("locationchangefathom",trackPageview))}function spaHash(){window.addEventListener("hashchange",trackPageview)}if(fathomScript.getAttribute("data-spa")||fathomScript.getAttribute("spa"))switch(fathomScript.getAttribute("data-spa")||fathomScript.getAttribute("spa")){case"history":spaHistory();break;case"hash":spaHash();break;case"auto":(void 0!==history?spaHistory:spaHash)()}var scriptUrl,trackerUrl="https://cdn.usefathom.com/";function encodeParameters(params){return params.cid=Math.floor(1e8*Math.random())+1,"?"+Object.keys(params).map(function(k){return encodeURIComponent(k)+"="+encodeURIComponent(params[k])}).join("&")}function qs(){for(var pair,data={},pairs=window.location.search.substring(window.location.search.indexOf("?")+1).split("&"),i=0;i<pairs.length;i++)pairs[i]&&(pair=pairs[i].split("="),-1<["keyword","q","ref","s","utm_campaign","utm_content","utm_medium","utm_source","utm_term","action","name","pagename","tab","via","gclid","msclkid"].indexOf(decodeURIComponent(pair[0])))&&(data[decodeURIComponent(pair[0])]=decodeURIComponent(pair[1]));return data}function trackingEnabled(){var fathomIsBlocked=!1;try{fathomIsBlocked=window.localStorage&&window.localStorage.getItem("blockFathomTracking")}catch(err){}var prerender="visibilityState"in document&&"prerender"===document.visibilityState,isExcludedDomain=-1<excludedDomains.indexOf(window.location.hostname),isAllowedDomain=!(0<allowedDomains.length)||-1<allowedDomains.indexOf(window.location.hostname);if(!fathomIsBlocked&&!prerender&&!honorDNT&&!isExcludedDomain&&isAllowedDomain)return!0}function getLocation(params){var a,location=window.location;return void 0===params.url?canonical&&document.querySelector('link[rel="canonical"][href]')&&((a=document.createElement("a")).href=document.querySelector('link[rel="canonical"][href]').href,location=a):(location=document.createElement("a")).href=params.url,location}return fathomScript.src.indexOf("cdn.usefathom.com")<0&&((scriptUrl=document.createElement("a")).href=fathomScript.src,trackerUrl="https://cdn.usefathom.com/"),document.addEventListener("visibilitychange",function(){"hidden"===document.visibilityState&&sendDeparturePing()}),window.addEventListener("pagehide",sendDeparturePing),auto&&(document.prerendering?document.addEventListener("prerenderingchange",()=>window.fathom_captaincore.trackPageview(),{once:!0}):setTimeout(function(){window.fathom_captaincore.trackPageview()})),{siteId:siteId,send:function(params){var img;trackingEnabled()&&((img=document.createElement("img")).setAttribute("alt",""),img.setAttribute("aria-hidden","true"),img.style.position="absolute",img.src=trackerUrl+encodeParameters(params),img.addEventListener("load",function(){img.parentNode.removeChild(img)}),img.addEventListener("error",function(){img.parentNode.removeChild(img)}),document.body.appendChild(img))},beacon:function(params){trackingEnabled()&&navigator.sendBeacon(trackerUrl+encodeParameters(params))},trackPageview:function(params){var hostname,pathnameToSend,location=getLocation(params=void 0===params?{}:params);""!==location.host&&(hostname=location.protocol+"//"+location.hostname,pathnameToSend=location.pathname||"/","hash"===fathomScript.getAttribute("data-spa")&&(pathnameToSend+=location.hash),this.send({h:hostname,p:pathnameToSend,r:params.referrer||(document.referrer.indexOf(hostname)<0?document.referrer:""),sid:this.siteId,qs:JSON.stringify(qs())}),pageStart=Date.now(),currentHostname=hostname,currentPathname=pathnameToSend,currentSiteId=this.siteId,currentQueryString=JSON.stringify(qs()))},trackGoal:function(code,cents){var location=getLocation({}),hostname=location.protocol+"//"+location.hostname;this.beacon({gcode:code,gval:cents,qs:JSON.stringify(qs()),p:location.pathname||"/",h:hostname,r:document.referrer.indexOf(hostname)<0?document.referrer:"",sid:this.siteId})},trackEvent:function(name,payload={}){var location=getLocation({}),hostname=location.protocol+"//"+location.hostname;this.beacon({name:name,payload:JSON.stringify(payload),p:location.pathname||"/",h:hostname,r:document.referrer.indexOf(hostname)<0?document.referrer:"",sid:this.siteId,qs:JSON.stringify(qs())})},setSite(siteId){this.siteId=siteId},blockTrackingForMe:function(){window.localStorage?(window.localStorage.setItem("blockFathomTracking",!0),alert("You have blocked Fathom for yourself on this website.")):alert("Your browser doesn't support localStorage.")},enableTrackingForMe:function(){window.localStorage&&(window.localStorage.removeItem("blockFathomTracking"),alert("Fathom has been enabled for this website."))},isTrackingEnabled:function(){return!0===trackingEnabled()}}})();
JSEOF