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

ClickPost vs. EasyPost

One integration. Infinite Impact. Unlock real-time tracking, cut shipping costs, reduce returns, and boost customer retention — all with ClickPost.

Trusted by 450+ global brands

A Quick Comparison of ClickPost and EasyPost:

Agile End-to-End Shipping Automation Fully automated, flexible end-to-end shipping, with API-first integrations and AI-driven intelligence 1 2
Scalable Delivery Accuracy Granular view on delays, stuck shipments, lost parcels, proactive alerts for on-time delivery 1 2
Post-Purchase Efficiency & Cost Control Hyper-personalized customer interactions, milestone-based notifications, feedback collection, personalized returns instructions 1 2
Customizable EDD Logic Custom-built models, EDD modified according to shipping speed and delivery types 1 2
EDD Breach Detection and Resolution Automatically detects breaches, revises EDDs, and updates tracking portal] 1 3
Advanced Carrier Selection Algorithm Automated carrier selection based on performance and multiple parameters 1 2
Plug and Play EDD Solution EDD API and widget, easily integrable throughout the website 1 3
Omnichannel Shipment & Return Updates Real-time notifications across SMS, Email, IVR, and WhatsApp at each critical milestone 1 3
Shipping Rate Aggregation Aggregates rates from multiple carriers and offers discounted shipping rates 3 1
Automated Carrier Selection by Rates Automated algorithm for selecting the most cost-effective shipping carrier 1 1
Flexible, Pre-Built Notification Templates Customizable pre-designed templates, language localization, additional customizations 1 3
Enterprise-ready Branded Tracking Completely customizable with whitelabeling, domain masking, marketing assets, feedback collection 1 2
Personalized Product Cross-Sales Personalized product recommendation on the tracking page for cross-selling and incremental revenue 2 3
Efficient Order Cancellation Management Allows easy order cancellation, notifies all stakeholders through webhook or API 1 1
Hyper-Configurable Returns Policy & Automatic Enforcement Advanced hyperconfigurality to return and exchange policies and automated refund mechanism 1 3
Smart Returns to Exchange Conversion Seamless return to exchange conversion on the dashboard, personalized exchange nudges 1 3
Flexible Exchange Options Site-wide exchanges, reconciling price difference in the same flow 1 3
Advanced Automated Refunds Triggers refunds at designated milestones, offers gift-card and store-credit, tracks refund status 1 3
Intelligent Order Routing Sends orders to the right location, choosing the best carrier 1 2
Scalable Carrier Network Integration Supports global carriers and partners, integrations completed in a day 1 2
Systematized Serviceability Verification Verifies address, checks serviceability and operational hours based on pick-up and drop-off 1 2
Streamlined Address Verification Dedicated AI for address verification, auto-review, and postal code detection 3 1
Comprehensive Reporting and Analytics Delivers logistics insights, including carrier performance, notifications, and SLA data 1 2
Automated Proof-of-Delivery Automatically fetches proof of delivery with dashboard logs for single and multi-piece shipments 1 2

** Instructions: 

  • Column 1: Name of the Feature
  • Column 2: Description of the feature
  • Column 3: Brand 1 details
  • Column 4: Brand 2 details
  • Column 5: Brand 3 details

Note: Column 3, 4 and 5 will accept value only "1" or "2" or "3". Column 5 will be there if there two external brands are considered. Otherwise Column 3 will be "Other" and Column 4 will be "Clickpost".

1 -> Advanced

2 -> Intermediate

3 -> Limited

ClickPost EasyPost
ClickPost
EasyPost

Who’s the final winner?

The Answer is ClickPost!

Fast-scaling brands expect more from multicarrier shipping than just rate shopping. They want faster delivery, real-time insights, and more control over logistics outcomes that directly contribute to revenue and retention. ClickPost delivers on all fronts with an agile, ROI-focused multi-carrier shipping and post-purchase engine.  

With a large library of 550+ global and domestic carriers, ClickPost offers wider serviceability access alongside granular performance monitoring.  Its Control Tower surfaces carrier-level SLA breaches and delivery delays.  As a first-of-its kind solution, it also offers warehouse-level visibility into exceptions like stuck or lost parcels—generating holistic tracking. 

As a result, ClickPost reduces delivery TAT and meets over 93% of delivery expectations. While it adds automation and intelligence at scale, EasyPost users often report limitations in operational efficiency as volumes grow. Its customizable logic for EDD, carrier allocation, and returns workflows helps brands cut shipping costs by over 30%.

Though EasyPost’s discounted rates work well for US-based shipping, ClickPost goes further. It reduces customer order-related queries by 56%, converts 54% of returns into exchanges, and retains 40% of return value as in-store credit. With ClickPost, you turn refunds into revenue and customer support into loyalty.

Frequently asked questions (FAQ's)

Which platform—ClickPost or EasyPost—is better suited for enterprise-level logistics automation?

ClickPost enables 550+ multi-carrier integration, diverse delivery options, wider serviceability, last-mile efficiency, and cross-border logistics. It reduces order processing time, automates carrier selection, enables real-time tracking, and streamlines returns. EasyPost unlocks pre-negotiated rates but lacks the depth of logistics automation and post-purchase control ClickPost offers.

Between ClickPost and EasyPost, which offers more advanced tracking and delivery visibility features?

ClickPost provides real-time visibility with minute-level updates on a centralized dashboard. Brands can drill into carrier performance, EDD adherence, failed deliveries, and Turnaround Time, lost parcels at warehouse level. This enables proactive exception handling. EasyPost focuses on delivery status but lacks granular insights like stuck parcels, or delivery-stage failure breakdowns.

How does ClickPost's support for NDR and failed deliveries compare to EasyPost's functionality?

ClickPost has a dedicated NDR management module that automates the process of handling failed deliveries. It categorizes reasons for non-delivery, sends resolution prompts to customers, and syncs updates with carriers, thus reducing Return to Origin (RTO) rates. In contrast, EasyPost lacks a comparable automated or manual automated workflows for failed delivery resolution.

How do pricing models compare between ClickPost and EasyPost?

ClickPost offers flexible, usage-based pricing with full access to advanced features from the start. EasyPost’s free plan suits smaller shipment volumes, but several key capabilities—like advanced tracking and custom carrier integrations—are only available on enterprise plans, which impacts scaling flexibility for enterprises.

Streamline your shipping experience with ClickPost

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