FAMILY MONEY · CLOUDFLARE
Update the wrapper. Upload the corrected ZIP.
Google places its banner outside your app. This update opens the tracker as soon as it loads and measures the banner space automatically to keep it fitted to your screen.
- In the small Apps Script wrapper project, replace all of
Code.gswith the code below. Keep the existing MoneyTracker library dependency. - Save. Choose Deploy → Manage deployments → Edit → New version → Deploy. Update the existing deployment to keep its URL.
- This ZIP opens
https://deb.s.gy/money. It follows the Google deployment assigned to that short link. - Upload MoneyTracker_Cloudflare.zip using Cloudflare Pages → Direct Upload, then deploy.
The library itself needs no update for this step. The app’s login and Google Sheets connection continue inside Google’s frame.
Replacement Code.gs
/** Cloudflare embedding update. Replace the wrapper Code.gs in full. */
/** Add the library as MoneyTracker. Setup/repair or first web open prepares all sheets. */
function mtContext_() {
var properties = PropertiesService.getScriptProperties();
var active = SpreadsheetApp.getActiveSpreadsheet();
if (active) properties.setProperty('MT_SSID', active.getId());
return {
spreadsheetId: active ? active.getId() : properties.getProperty('MT_SSID'),
properties: properties,
cache: CacheService.getScriptCache(),
lock: LockService.getScriptLock()
};
}
function api(request) { return MoneyTracker.api(request, mtContext_()); }
function setup() { return MoneyTracker.setup(mtContext_()); }
function onOpen(e) { MoneyTracker.onOpen(mtContext_()); }
function mtOnEdit(e) { MoneyTracker.handleEdit(e, mtContext_()); }
function mtOnChange(e) { MoneyTracker.handleChange(e, mtContext_()); }
function mtDaily() { MoneyTracker.runDaily(mtContext_()); }
function openApp() { return MoneyTracker.openApp(mtContext_()); }
function refreshNow() { return MoneyTracker.refresh(mtContext_()); }
function reportThisMonth() { return MoneyTracker.reportThisMonth(mtContext_()); }
/* Replace doGet in the small including-project Code.gs with this function.
* Add mtCloudflareBridge_ once. No MoneyTracker library version change is needed.
*/
function doGet(e) {
var output = MoneyTracker.serve(mtContext_(), e);
var params = e && e.parameter || {};
var origin = String(params.mt_host || '');
var channel = String(params.mt_channel || '');
if (!/^https:\/\/[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?(?::[1-9][0-9]{0,4})?$/i.test(origin) ||
!/^[a-f0-9]{32}$/.test(channel)) return output;
// Optional: a comma-separated MT_EMBED_ORIGINS Script Property limits hosts.
var allowed = String(PropertiesService.getScriptProperties().getProperty('MT_EMBED_ORIGINS') || '')
.split(',').map(function(value) { return value.trim(); }).filter(Boolean);
if (allowed.length && allowed.indexOf(origin) < 0) return output;
var config = JSON.stringify({ origin: origin, channel: channel }).replace(/</g, '\\u003c');
var script = '<script>(' + mtCloudflareBridge_.toString() + ')(' + config + ');</script>';
var html = output.getContent();
var end = html.toLowerCase().lastIndexOf('</body>');
output.setContent(end < 0 ? html + script : html.slice(0, end) + script + html.slice(end));
return output.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}
/* Runs only in the browser after being injected by doGet. It shares dimensions
* only; login tokens, PINs, spreadsheet data and RPC stay inside Google's frame.
*/
function mtCloudflareBridge_(config) {
if (window.top === window) return;
var queued = false;
var latest = null;
var topWindow = window.top;
function send(type, extra) {
var data = { type: type, version: 1, channel: config.channel };
Object.keys(extra || {}).forEach(function(key) { data[key] = extra[key]; });
try { topWindow.postMessage(data, config.origin); } catch (e) { /* Wait for the host to be ready. */ }
}
function measure() {
if (queued) return;
queued = true;
setTimeout(function() {
queued = false;
if (!latest) return;
send('mt-app-viewport', {
sequence: latest.sequence,
width: window.innerWidth,
height: window.innerHeight
});
}, 0);
}
window.addEventListener('message', function(event) {
var data = event.data;
if (event.source !== topWindow || event.origin !== config.origin || !data ||
data.type !== 'mt-host-viewport' || data.version !== 1 || data.channel !== config.channel ||
!Number.isSafeInteger(data.sequence) || data.sequence < 1 ||
!Number.isFinite(data.width) || !Number.isFinite(data.height) || data.width <= 0 || data.height <= 0) return;
if (latest && data.sequence <= latest.sequence) return;
latest = data;
measure();
});
function resized() { send('mt-app-resize'); }
window.addEventListener('resize', resized, { passive: true });
window.addEventListener('orientationchange', resized, { passive: true });
window.addEventListener('pageshow', function() { send('mt-app-ready'); }, { passive: true });
document.addEventListener('visibilitychange', function() { if (!document.hidden) resized(); });
send('mt-app-ready');
}
Download replacement code · Full instructions · Open the tracker