and runs during HTML parse, but hubspotutk is set by js.hs-analytics.net, measured loading at ~834ms. On a first visit the cookie does not exist yet, so a single read returns nothing and the visitor gets no external ID at all — and a first visit is exactly what an ad click is. So poll briefly until HubSpot sets it. The SDK loads lazily (~4.5s) and replays a queue, so an init queued a second or two in still lands before any events are transmitted. */ (function attachExternalId() { var attempts = 0; var MAX_ATTEMPTS = 40; /* 40 x 200ms = 8s, then give up quietly */ var timer = null; function tryAttach() { var raw = getExternalId(); if (!raw) { if (++attempts >= MAX_ATTEMPTS && timer) clearInterval(timer); return; } if (timer) clearInterval(timer); sha256Hex(raw).then(function (hash) { oaiq("init", { user: { external_id_sha256: hash } }); }).catch(function () {}); } tryAttach(); /* returning visitor: immediate */ if (!getExternalId()) timer = setInterval(tryAttach, 200); })(); /* --------------------------------------------------------------------------- 2. Load the SDK off the critical path Whichever comes first: the main thread going idle after load, or the first sign of real user intent. No preconnect on purpose — a TLS handshake during LCP for a script we deliberately deferred is a net loss. Measured on clickpost.ai: load event 3614ms, SDK fetched 4508ms. ------------------------------------------------------------------------ */ var loaded = false; var INTENT = ["pointerdown", "keydown", "scroll"]; function loadSdk() { if (loaded) return; loaded = true; INTENT.forEach(function (t) { removeEventListener(t, loadSdk, { passive: true }); }); var s = document.createElement("script"); s.src = SDK; s.async = true; s.fetchPriority = "low"; document.head.appendChild(s); } INTENT.forEach(function (t) { addEventListener(t, loadSdk, { passive: true, once: true }); }); addEventListener("load", function () { window.requestIdleCallback ? requestIdleCallback(loadSdk, { timeout: 2500 }) : setTimeout(loadSdk, 1500); }, { once: true }); /* --------------------------------------------------------------------------- 3. Conversion id sha256(lowercase(email) + "|" + formId + "|" + ISO-hour), first 20 hex, "lead_" prefix. - email lowercased/trimmed so casing does not fork the id - formId keeps two different forms in the same hour from colliding - the hour bucket is only the server's fallback; the id computed here is sent to the relay verbatim, so the two paths cannot disagree even when a submit straddles an hour boundary Ads Manager's own sample omits event_id. We send it so the pixel event and the relay event collapse into one conversion instead of counting twice. ------------------------------------------------------------------------ */ function buildEventId(email, formId) { var seed = [ String(email || "").trim().toLowerCase(), String(formId || ""), new Date().toISOString().slice(0, 13) ].join("|"); return crypto.subtle.digest("SHA-256", new TextEncoder().encode(seed)).then(function (buf) { var hex = Array.prototype.map.call(new Uint8Array(buf), function (b) { return b.toString(16).padStart(2, "0"); }).join(""); return "lead_" + hex.slice(0, 20); }); } /* Guards a re-fire from the history.pushState that book-a-demo-core.js runs after submit, and from back-navigation onto the same state. */ function firedOnce(id) { try { if (sessionStorage.getItem("oaiq_" + id)) return true; sessionStorage.setItem("oaiq_" + id, "1"); return false; } catch (e) { return false; /* private mode / blocked storage: fire rather than lose it */ } } /* Path 2. keepalive lets the request finish even if the page navigates away. Failures are swallowed deliberately: a reporting call must never surface an error to someone who just submitted a form. The relay hashes the email server-side into user.emails_sha256 and adds the caller's IP and user agent, so this event carries the same match signals the pixel gets for free. */ function sendToRelay(email, formId, eventType, eventId) { try { var payload = { token: RELAY_TOKEN, email: email, form_id: formId || "", event_type: eventType, event_id: eventId, /* verbatim, so both paths always match */ source_url: location.href }; var oppref = getOppref(); if (oppref) payload.oppref = oppref; var externalId = getExternalId(); if (externalId) payload.external_id = externalId; fetch(RELAY_URL, { method: "POST", keepalive: true, headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) }).catch(function () {}); } catch (e) {} } /* Capture the email while the form is still on the page. onFormSubmitted does not reliably carry submissionValues, and by then the form may be removed. */ var lastEmail = ""; document.addEventListener("submit", function (e) { var f = e.target; if (!f || !f.querySelector) return; var i = f.querySelector('input[name="email"], input[type="email"]'); if (i && i.value) lastEmail = i.value; }, true); /* Every HubSpot form on the site reports through this one message event, so no module or theme JS needs editing to add coverage. */ window.addEventListener("message", function (e) { var d = e.data; if (!d || d.type !== "hsFormCallback" || d.eventName !== "onFormSubmitted") return; var email = (d.data && d.data.submissionValues && d.data.submissionValues.email) || lastEmail; if (!email) return; /* without an email there is no stable id to dedupe on */ var eventType = EVENT_BY_FORM[d.id] || EVENT_DEFAULT; buildEventId(email, d.id).then(function (id) { if (firedOnce(id)) return; oaiq("measure", eventType, { type: DATA_TYPE }, { event_id: id }); /* path 1 */ sendToRelay(email, d.id, eventType, id); /* path 2 */ }); }); })();

91ÊÓÆµ

See where your logistics stands on automation Start assessment

Home > Blog >

Cracking the 'Why': How We Rethought Product Performance Monitoring in a Scaling Startup

Cracking the 'Why': How We Rethought Product Performance Monitoring in a Scaling Startup

Omair Khan
By Omair Khan

Ready to ship smarter? Talk to our logistics experts.

Trusted by 600+ brands

In this blog

    One of the most profound shifts I’ve experienced in product engineering is the realization that the “w³ó²ââ€�  behind a problem is more powerful than the “w³ó²¹³Ùâ€� or the “h´Ç·Éâ€�. In fact, if you deeply understand the why, the what starts to reveal itself almost naturally—and the how becomes a matter of taste, preference, and execution style.

    This post is less about a shiny solution and more about the hard-earned clarity that shaped it.

    From Fragmentation to Observability

    Speed vs. Structure: The Startup Balancing Act

    In the early days of Clickpost, our north star was speed. Speed to deliver new products. Speed to ship custom enterprise features. Our products were lean, clean, and purpose-built—and it wasn’t hard to keep tabs on how they performed. Engineering intuition and customer feedback often told us everything we needed to know.

    But products scale. Customers grow. And evolve.

    Soon enough, our once-simple product lines branched out—more features, more sub-products, more interdependencies. If you draw a diagram of our offerings today, it would resemble a tree with multiple levels and deeply connected nodes. And when an issue popped up in a parent node, its ripple effects would cascade across the branches—affecting downstream products in subtle but critical ways.

    To keep pace, each team built its own set of monitoring scripts and internal tools. These were bootstrapped, functional, but ultimately fragmented. No customer had visibility into what was happening under the hood.

    Eventually, enterprise clients began to build their own internal flows—custom solutions to monitor our system’s performance from their end. This wasn't just problematic—it was dangerous. Each customer had a different, often incorrect, understanding of how our system was supposed to behave. And so they leaned on us.

    Suddenly, internal teams were spending valuable time generating ad hoc reports, pulling metrics manually, and translating system behavior into something the customer could understand.

    This wasn’t scalable. It was noisy and expensive—especially when you factor in the human cost of repeated firefighting and lost focus.

    When performance tracking becomes a bandwidth sink

    At one point, we realized that simply tracking performance had become its own mammoth task—requiring significant engineering bandwidth, with focused on system optimization.

    We were burning cycles explaining ourselves to customers instead of focusing on improving the product itself.

    That was the turning point. We needed a proactive, standardized, and self-serve system to monitor and visualize product performance.

    A system that:

    • Worked across all product lines

    • Was easy to understand and adopt
    • Gave customers direct visibility into what mattered

    And perhaps most importantly—it had to be flexible enough to handle different product requirements without becoming a blocker.

    From Ad Hoc to Operational Transparency

    The vision was to surface key performance metrics directly to customers through visual dashboards. No more back-and-forth. No more “Can you run a script to check this?� messages on Slack.

    But to get there, we had to go back to the fundamentals.

    We needed a cultural shift in how we thought about KPIs and metrics. Instead of tackling monitoring later, we needed to integrate it into the design of every new feature and product—from the start.

    A Bottom-Up Metric Mindset

    Take something like order creation (OC) integration—a common, well-understood flow.

    Every new order is a transaction in our system. For each transaction, we can define:

     

    • Dimensions — like enterprise ID, account ID, reference number
    • Metrics — like courier partner API latency, status codes

    If every team captured these metrics consistently, we could aggregate them effortlessly—daily, weekly, monthly—to understand real-world product performance at scale.

    These metrics became the foundation for building our internal for cheking metrics, helping both developers and stakeholders observe performance trends, spot bottlenecks, and validate improvements in near real time.

    This bottom-up approach doesn’t just help with visibility—it unlocks long-term observability.

    Evaluating Tools: Finding the Right Fit

    We explored a bunch of stacks. Prometheus with time-series databases, Elasticsearch with Kibana, and more. Our core requirement was that the solution shouldn’t just be about monitoring—it should be extensible for future observability and visibility needs.

    Ultimately, we landed on:

     

    • Elasticsearch for data storage and aggregation
    • Grafana for beautiful, customizable visualizations

    This combination gave us the flexibility and scalability we needed. It checked every box—developer-friendliness, ease of integration, powerful querying and aggregations.

    Adoption, Abstraction & The 'PFAL' Approach

    Now comes the tricky part: adoption.

    We’re currently working on embedding this monitoring mindset into our development workflow. From a code perspective, we’ve built abstractions so that developers don’t have to worry about plumbing. They can simply follow what I like to call the Push first, ask later.

    Just send a well-defined payload—with dimensions and metrics—into Elasticsearch, and it shows up on Grafana.

    At the moment, product owners are responsible for defining KPIs and metrics in every design document. But in the future, we’ll automate this too—making it a seamless part of our development lifecycle.

    In Closing: The Cost of Ignoring the 'Why'

    This journey wasn’t sparked by a fancy tech stack or a visionary whiteboard sketch. It started because we were bleeding time, attention, and trust—internally and externally.

    By focusing on the why—Why are customers frustrated? Why are we burning bandwidth? Why do issues keep escalating?—we arrived at a solution that was far more robust than anything we could’ve designed with just a “what tech should we use?� mindset.

    And that’s the real takeaway.

    If you get the why right, everything else starts to fall into place.

     

    The Logistics Automation Platform for E-commerce

    Momentum Leader - G2 Users Most Likely To Recommend - G2 Best Results Mid-Market - G2
    . window.disableHubSpotCookieBanner = true; function killNative() { var n = document.getElementById("hs-eu-cookie-confirmation"); if (n && n.parentNode) { n.parentNode.removeChild(n); return true; } return false; } killNative(); if (window.MutationObserver) { var mo = new MutationObserver(function () { killNative(); }); mo.observe(document.documentElement, { childList: true, subtree: true }); setTimeout(function () { mo.disconnect(); }, 15000); } var COOKIE = "cp_cookie_consent"; var EU = ["at","be","bg","hr","cy","cz","dk","ee","fi","fr","de","gr","hu","ie","it","lv","lt","lu","mt","nl","pl","pt","ro","sk","si","es","se","gb","uk","is","li","no","ch"]; function readCookie(nm) { var m = document.cookie.match(new RegExp("(?:^|; )" + nm + "=([^;]*)")); return m ? decodeURIComponent(m[1]) : null; } function writeCookie(nm, val, days) { var d = new Date(); d.setTime(d.getTime() + (days * 864e5)); document.cookie = nm + "=" + encodeURIComponent(val) + ";expires=" + d.toUTCString() + ";path=/;SameSite=Lax" + (location.protocol === "https:" ? ";Secure" : ""); } function stored() { var raw = readCookie(COOKIE); if (!raw) return null; try { var o = JSON.parse(raw); if (typeof o.analytics === "boolean") return o; } catch (e) {} return null; } function apply(state, revoke) { window._hsp = window._hsp || []; window._hsp.push(["setHubSpotConsent", { analytics: !!state.analytics, advertisement: !!state.advertisement, functionality: !!state.functionality }]); if (revoke && !state.analytics && !state.advertisement && !state.functionality) { window._hsp.push(["revokeCookieConsent"]); } window.dataLayer = window.dataLayer || []; window.dataLayer.push({ event: "cp_cookie_consent", cp_consent_analytics: !!state.analytics, cp_consent_advertisement: !!state.advertisement, cp_consent_functionality: !!state.functionality }); document.documentElement.setAttribute("data-cp-consent", "set"); } function inScope(banner) { if (banner.getAttribute("data-scope") !== "eu_only") return true; var geo = (document.body.getAttribute("data-geo_location") || "").toLowerCase(); if (!geo) return true; return EU.indexOf(geo) !== -1; } function init(banner) { var days = parseInt(banner.getAttribute("data-days"), 10) || 180; var prefs = banner.querySelector("[data-cpcb-prefs]"); var compact = banner.querySelector('[data-cpcb-actions="compact"]'); var expanded = banner.querySelector('[data-cpcb-actions="expanded"]'); var toggles = banner.querySelectorAll("[data-cpcb-toggle]"); function show() { banner.hidden = false; requestAnimationFrame(function () { banner.classList.add("is-visible"); }); } function hide() { banner.classList.remove("is-visible"); setTimeout(function () { banner.hidden = true; }, 300); } function collapse() { if (!prefs) return; prefs.hidden = true; if (expanded) expanded.hidden = true; if (compact) compact.hidden = false; } function expand() { if (!prefs) return; prefs.hidden = false; if (compact) compact.hidden = true; if (expanded) expanded.hidden = false; } function paint(state) { Array.prototype.forEach.call(toggles, function (t) { var key = t.getAttribute("data-cpcb-toggle"); if (key === "necessary") { t.setAttribute("aria-checked", "true"); return; } t.setAttribute("aria-checked", state[key] ? "true" : "false"); }); } function fromToggles() { var state = { analytics: false, advertisement: false, functionality: false }; Array.prototype.forEach.call(toggles, function (t) { var key = t.getAttribute("data-cpcb-toggle"); if (key in state) state[key] = t.getAttribute("aria-checked") === "true"; }); return state; } function commit(state, revoke) { writeCookie(COOKIE, JSON.stringify({ analytics: !!state.analytics, advertisement: !!state.advertisement, functionality: !!state.functionality, v: 1, ts: Date.now() }), days); apply(state, revoke); hide(); } Array.prototype.forEach.call(toggles, function (t) { if (t.disabled) return; t.addEventListener("click", function () { t.setAttribute("aria-checked", t.getAttribute("aria-checked") === "true" ? "false" : "true"); }); }); banner.addEventListener("click", function (e) { if (!e.target || !e.target.closest) return; var btn = e.target.closest("[data-cpcb-action]"); if (!btn) return; var action = btn.getAttribute("data-cpcb-action"); if (action === "customise") { expand(); return; } if (action === "accept") { commit({ analytics: true, advertisement: true, functionality: true }, false); return; } if (action === "reject") { commit({ analytics: false, advertisement: false, functionality: false }, true); return; } if (action === "save") { commit(fromToggles(), true); return; } }); var existing = stored(); if (existing) { apply(existing, false); paint(existing); collapse(); } else if (!inScope(banner)) { // Out of the consent-required region: implied consent, banner never shown. commitSilently(); } else { collapse(); show(); } function commitSilently() { var all = { analytics: true, advertisement: true, functionality: true }; writeCookie(COOKIE, JSON.stringify({ analytics: true, advertisement: true, functionality: true, v: 1, ts: Date.now(), implied: true }), days); apply(all, false); } // Public re-open hook for a footer "Cookie settings" link. window.cpCookieBanner = window.cpCookieBanner || {}; window.cpCookieBanner.open = function () { var s = stored() || { analytics: false, advertisement: false, functionality: false }; paint(s); expand(); show(); }; } function boot() { var banners = document.querySelectorAll("[data-cpcb]"); if (!banners.length) return; init(banners[0]); document.addEventListener("click", function (e) { if (!e.target || !e.target.closest) return; var trigger = e.target.closest("[data-cp-cookie-settings]"); if (!trigger) return; e.preventDefault(); if (window.cpCookieBanner && window.cpCookieBanner.open) window.cpCookieBanner.open(); }); } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", boot); } else { boot(); } })();