01. The Challenge & Core Requirement
PhysicalStack tracks daily buy/sell quotes from 57+ precious metals dealers across 13 countries (USA, UK, Canada, Australia, Germany, Switzerland, Singapore, UAE, Turkey, India, Sweden, Norway, Denmark). Data is scraped into multiple Google Sheets tabs—one per product (Silver Eagle, Gold Coin, 10oz Bar, etc.)—with 17 product configurations spanning global and country-specific markets.
The publication needed interactive charts embedded directly inside Ghost CMS member pages. Previously, static chart screenshots were uploaded manually, making them unreadable on mobile and stale the moment data updated.
02. My Core Role & Dashboard Implementation
My responsibility was designing the client-side Plotly dashboards, structuring the data pipeline from Sheets to frontend, and building the Ghost CMS embed injection code. The modular JS architecture (config.js, data.js, utils.js, app.js) is hosted on Cloudflare Pages and loaded into Ghost via an HTML injection block.
- Ghost CMS Embed with MutationObserver Guard: Injected a custom
MutationObserverwrapper that prevents Ghost's content engine from rewriting the dashboard DOM—ensuring Plotly renders survive Ghost's internal page lifecycle. - Cloudflare Pages Functions Proxy: Built a Cloudflare Worker (
_worker.js) that proxies Google Sheets API requests via/api/sheetsand FX rate lookups via/api/fx, keeping API keys server-side. - Data Feed Transition: Migrated from direct Google Sheets CSV ingestion (via PapaParse) to a database backend at
db.physicalstack.comfor production reliability—including spot price data, dealer metadata, and country mappings. - Multi-Market Product Tabs: Configured 17 chart products across silver, gold, and country-specific markets (Turkey Gram Altın, India Gram Gold Bar) with tab navigation, per-dealer color assignment, and country-based filtering.
- Teaser Embed for Non-Members: Built a separate
teaser-embed-v2.htmlwith 30-day inline preview data for public-facing pages, loading Plotly charts from bundled JSON rather than authenticated API calls.
03. Ghost CMS Injection Code
<!-- Ghost CMS Inject — PhysicalStack Dashboard Embed -->
<section class="ps-charts-embed-section">
<!-- MutationObserver guard: prevent Ghost from rewriting dashboard DOM -->
<script>(function () {
var _MO = window.MutationObserver;
window.MutationObserver = function (cb) {
return new _MO(function (records) {
var f = records.filter(function (r) {
return !r.target.closest || !r.target.closest('.ps-mount');
});
if (f.length) cb(f);
});
};
window.MutationObserver.prototype = _MO.prototype;
})();</script>
<link rel="stylesheet" href="https://physicalstack.pages.dev/src/style.css">
<div class="ps-mount" style="min-height:98dvh;"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.4.1/papaparse.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/plotly.js/2.35.3/plotly-basic.min.js"></script>
<script src="https://physicalstack.pages.dev/src/config.js"></script>
<script src="https://physicalstack.pages.dev/src/data.js"></script>
<script src="https://physicalstack.pages.dev/src/utils.js"></script>
<script src="https://physicalstack.pages.dev/src/app.js"></script>
</section> 04. Key Deliverables & Outcomes
The embedded Plotly dashboards allow PhysicalStack to publish live, interactive dealer-comparison charts directly within Ghost CMS member pages. Data updates daily at US spot open—all embedded charts across the publication reflect new prices automatically without manual re-publishing. The teaser embed provides a compelling 30-day preview for non-members to drive subscription conversions.