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 >

Dynamic Polling Scheduler: Reinventing Shipment Tracking at ClickPost

Dynamic Polling Scheduler: Reinventing Shipment Tracking at ClickPost

Hritik Karwasra
By Hritik Karwasra

Ready to ship smarter? Talk to our logistics experts.

Trusted by 600+ brands

In this blog

    At ClickPost, we’ve always believed that logistics technology should simplify operations, delight customers, and scale effortlessly. With e-commerce volumes growing every day, traditional shipment tracking systems were struggling to keep up. That’s why we built our Dynamic Polling Scheduler — a smarter, scalable way to track millions of shipments while keeping carrier partners, enterprises, and customers happy.

    The Old Way Wasn’t Good Enough

    Our earlier polling system worked on a simple schedule: check shipments every two hours in one big batch. But this approach came with real challenges:

     

    • Courier API overload → Millions of requests sent in one shot created sudden traffic spikes.

    • Slow visibility → Issues were only detected every two hours.

    • Missed SLAs → Courier rate-limits blocked us, creating delaying updates.

    • No account-level control → Every customer got the same 2-hour polling, whether they needed it or not.

    For fast-moving e-commerce brands, these delays and inefficiencies could impact customer trust and delivery promises.

    A Smarter Solution: Dynamic Polling

    The Dynamic Polling Scheduler changes how shipments are tracked by spreading the work evenly across time and accounts. Instead of traffic spikes, shipments are polled continuously in 1-minute slices, ensuring smooth operations and fresher updates.

    Here’s what makes it powerful:

     

    • Configurable Per Account → Each enterprise can set its own polling frequency.

    • Smooth Load Distribution → Shipments spread across polling frequency windows, no more courier overload.

    • Real-Time Monitoring → Issues detected in under 10 minutes, not 2 hours.

    Deep Configurability: Built for Every Business

    Not every enterprise has the same needs. A high-volume marketplace, a niche D2C brand, and a logistics provider will all want different tracking behaviors. Dynamic Polling makes that possible:

     

    1. Per-Account Polling Intervals

    Each customer can define how frequently their shipments should be polled. For example:


      • A large electronics retailer may want every 60 minutes for time-sensitive deliveries.

      • A lifestyle brand with reliable couriers may prefer every 180 minutes to reduce load.

    2. Automatic Adjustments

    Polling frequency adapts dynamically:


      • Accounts with strong webhook coverage get fewer polls (up to 12 hours apart).

      • Accounts without webhook coverage stay on frequent cycles.

    3. Granular Control at Scale

    Configuration can be applied at:


      • Enterprise Level → One setting for the whole brand.

      • Courier Level → Different polling intervals per courier partner.

    This configurability-first approach ensures that every brand gets exactly the level of visibility it needs — without overloading couriers or wasting resources.

    Real-Life Impact: From API Throttling to Zero Tickets

    Before Dynamic Polling, one of the biggest issues we faced was API throttling. Many courier partners impose strict rate limits, and our older architecture made burst calls that often exceeded these thresholds.

    A clear example is , which has a rate limit of just 8 transactions per second. Under the old system, almost all requests to ATS would get rate-limited, leading to delays and missed updates.

    With Dynamic Polling, those issues have disappeared:

    • 100% reduction in rate-limits → Every request now succeeds, staying within courier thresholds.

    • 0 tickets raised → Earlier, we received at least 5 client complaints per week about delayed or missing updates due to polling failures. Since deployment, we’ve seen zero tickets in the last 4 weeks.

    • Webhook reliability support → Previously, if webhooks failed or were delayed, customers immediately noticed gaps in tracking. Now, polling ensures full coverage with no client impact.

    • Custom Configurations → Earlier, we could not reduce polling intervals below 2 hours, even when clients asked. Now, we can adjust polling cycles instantly, via self-service, meeting customer-specific needs with a single click.

    Success Metrics

    This chart data for Shiprocket

    This chart data for Amazon Traking Services

    Note:

    • green color indicates - rate limited
    • blue color indicates - api success but no new updates in awb status
    • red color indicates - api success and and new updates received

    The result?

    Clients are seeing fewer tracking issues, faster updates, and higher satisfaction. And our support team no longer spends hours resolving repetitive tickets — freeing up time for more strategic work.

    Key Benefits for Businesses

    1. Faster, fresher updates → Customers see real-time status, reducing “Where is my order?� calls.

    2. Tailored Flexibility → Each account decides its own tracking priorities.

    3. Courier-friendly → Keeps traffic predictable, strengthening courier relationships.

    4. On-time delivery updates → Keeps SLAs safe and reduces risk of breaches.

    5. Uniform polling per shipment → Every shipment is tracked at its exact configured interval, avoiding delays from batch dumps. This ensures predictable polling gaps, strict SLA adherence, and easier debugging when issues arise.

    6. Cost efficiency → Optimized polling reduces unnecessary API calls.

    7. Scalable growth → Handles 10x shipment volumes with the same infrastructure.

    Who Benefits Most?

     

    • Large Enterprises & Marketplaces → Manage millions of shipments with custom polling strategies per seller or courier.

    • E-commerce Brands → Gain control to optimize between cost efficiency and delivery speed.

    • Logistics Companies → Ensure urgent shipments are prioritized with higher polling frequency.

    • SaaS Platforms → Multi-tenant flexibility with isolated polling configurations.

    Why This Matters

    → For customers, it means fresher, more reliable tracking updates.
    → For brands, it means on-time delivery updates, cost savings, and fewer SLA breaches.
    → For courier partners, it means stable, predictable API traffic without spikes.

    The Dynamic Polling Scheduler is more than an engineering upgrade — it’s a business enabler. By transforming how tracking works at scale, ClickPost ensures that enterprises can grow faster, operate smarter, and keep customers happier.

    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(); } })();