By the Digital Empire Regulatory Research Team (PixelProof Analysis Team) · Reviewed by Andy Gaber, Founder, Digital Empire Holdings LLC · Published August 23, 2026 · Last updated August 23, 2026
Shopify Scripts and Shopify Functions cover overlapping ground: both let a merchant customize checkout logic on Shopify infrastructure without shipping a full server-side app. But they are separate systems from separate eras. Scripts were Ruby-based checkout scripts exclusive to Plus tenants, running on the legacy checkout that Shopify retired for migrated stores on Aug 26, 2026. Functions are WebAssembly-based extension code available on all tiers under Checkout Extensibility, with elevated capability scopes retained on Plus. For a merchant coming out of the migration deadline with a pile of ported logic and a Meta Pixel installation that needs to keep working, the practical question is what changed in the customer-event payload and where new Function-target logic can silently corrupt tracking hygiene. This guide walks the transition, the target-by-target tracking implications, and where PixelProof fits inside the post-migration monitoring stack.
Shopify Scripts were a Plus-exclusive Ruby scripting surface introduced to let merchants apply custom checkout logic without deploying an app. A Script ran inside a Shopify-managed Ruby sandbox during checkout, received the cart context as input, and could apply discounts, alter line items, gate shipping options, or modify payment gateway visibility. Script installation ran through the Script Editor admin surface (on Plus tenants only), and Scripts executed automatically during any checkout on the tenant. The Script API was intentionally narrow: a small set of hooks, a Ruby-only runtime, and no external network access from within the Script.
Shopify Functions are the modern replacement. Functions are developer-authored code compiled to WebAssembly, deployed as a Shopify app extension, and executed on Shopify infrastructure at specific defined checkout targets (cart transform, discount, delivery customization, payment customization, checkout validation, and additional targets that ship on the Shopify roadmap). Functions can be authored in Rust, JavaScript, or any Wasm-target language. The runtime is deterministic (no external network calls) and CPU-time capped, mirroring the sandbox properties Scripts had but with a wider set of hook points and a modern developer experience (git-based deployment, CLI tooling, and TypeScript type safety).
The overlap: both systems let a merchant customize checkout state server-side. The difference: Scripts were Plus-only, Ruby, admin-installed, and coupled to the legacy checkout; Functions are available on all tiers (with Plus-elevated scopes for certain targets), Wasm, app-extension-deployed, and coupled to Checkout Extensibility. Aug 26, 2026 was the operative cutover date for Plus merchants still on the legacy checkout: after that date, Scripts on the migrated checkout do not execute, and the port target is a Function against the equivalent Checkout Extensibility target.
The Aug 26, 2026 checkout.liquid deadline was the Shopify-published cutoff for Plus stores still on the legacy customized checkout. Alongside the checkout.liquid retirement, Scripts running on that legacy checkout surface stopped executing on migrated stores. Plus tenants had two paths: (1) migrate the store to Checkout Extensibility and port any Script logic to Shopify Functions on the corresponding targets, or (2) delay migration through whatever legacy exemption remained on their tenant, at the cost of losing sales-channel features that assumed Checkout Extensibility.
The tracking-integrity implication of a botched Script-to-Function port is direct: a Script that applied a fixed discount is replaced by a Function on the cart-transform or discount target. If the Function has slightly different logic (a bug in the port, a different rounding convention, a missed edge case for a specific product tag), the checkout_completed event payload downstream carries different totals, different line-item counts, or different discount codes than the pre-migration state. The Meta Pixel and Klaviyo integrations that consume that event downstream carry the difference silently, and attribution or flow logic drifts until the merchant catches the payload change.
Cart transform. Cart transform Functions modify the line-item composition of the cart before checkout, typically for bundle merging (converting a bundle SKU into its component SKUs at checkout for inventory purposes) or bundle expansion. The downstream customer-event payload reflects the transformed cart, not the pre-transform cart. Meta Pixel purchase events fire with the transformed line_items array; Klaviyo Placed Order metrics carry the same. Merchants who ran bundling via Scripts and are porting to cart-transform Functions should verify that the new payload matches their downstream attribution expectations, particularly if they had Meta ad campaigns optimized against the pre-transform SKU set.
Discount. Discount Functions apply programmatic discount logic (percentage-off, fixed-amount-off, or free-shipping) based on cart criteria. The downstream event payload carries the discounted total, the applied discount code (if the Function attaches one), and the applied discount amount. For Meta AEM (Aggregated Event Measurement) event optimization, the value field of the purchase event drives ad-optimization, and the value should typically be the post-discount amount the customer actually paid; a Function that applies discount correctly should therefore produce a clean value signal for Meta. A Function bug that fails to apply a discount or applies the wrong discount will fire a purchase event with an incorrect value, and Meta ad-optimization will optimize against the wrong signal.
Delivery customization. Delivery customization Functions modify the shipping-option set presented at checkout: hiding, renaming, or reordering shipping methods. The downstream event payload for the shipping_info_submitted or checkout_started event will reflect the customized shipping options. Merchants running Klaviyo shipping-selection flows that depend on the specific shipping method the customer chose should verify that the delivery-customization Function preserves the method identifiers those flows expect.
Checkout validation. Checkout validation Functions block the checkout Continue button until a custom validation resolves (a required field, a business-rule check, an inventory-availability re-verification). Validation Functions do not modify the event payload per se, but they change the timing of customer events: if the validation blocks, no subsequent payment_info_submitted or checkout_completed event fires until the customer resolves the validation. Merchants who track abandonment based on time-to-payment should account for validation-Function delays in that metric.
Payment customization. Payment customization Functions modify the payment-method set presented at checkout: hiding a payment method for certain cart criteria (for example, requiring a bank transfer above a threshold, or hiding cash-on-delivery for certain product categories). The downstream event payload for payment_info_submitted reflects the payment method the customer actually selected from the customized set.
The Shopify checkout event stream fires customer events in a defined order: standard events include page_viewed, product_viewed, cart_viewed, checkout_started, payment_info_submitted, and checkout_completed. Functions execute server-side before the corresponding customer event is emitted. A cart-transform Function runs before checkout_started fires (so the checkout_started event carries the transformed cart). A discount Function runs before the discount-applied event fires. A checkout-validation Function runs before checkout completion can proceed. This is important for merchants building Custom Pixels or server-side Conversions API integrations: the event payload the pixel receives is already post-Function, and the Custom Pixel does not need to (and cannot) re-apply the Function logic itself.
One consequence: server-side Meta Conversions API events fired from a Shopify Function-adjacent app (for example, a shipping-notification email service that fires a Purchase CAPI event when it sees the order) will typically fire on the completed order state, not the pre-Function cart state. Merchants who want to distinguish pre-discount and post-discount value in their Meta reporting must instrument that distinction in their Custom Pixel or in their CAPI integration explicitly; the Function output is a single post-transformation payload.
The recurring failure modes we see in the field on Script-to-Function port projects: (1) rounding differences between the Ruby math the Script used and the Rust or JavaScript math the Function uses, producing checkout_completed event values that are off by cents on some cart sizes; (2) product-tag or metafield read differences where the Script had access to a legacy metafield the Function does not (or vice versa), producing different discount application logic on the same cart; (3) currency-conversion edge cases in Multi-Origin tenants where a Script had implicit currency-conversion behavior that a Function needs to be explicit about, producing checkout_completed events in the wrong currency; (4) discount-code-application ordering differences where the Script applied discounts in one order and the Function applies them in another, producing different final totals; and (5) inventory-availability rechecking where a validation Function blocks a checkout after payment_info_submitted has already fired, producing a payment event with no matching completion event and skewing conversion funnels.
The common thread: none of these failure modes surface directly in the Function itself. They surface downstream in the customer-event payload, in the Meta Pixel purchase event, in the Klaviyo Placed Order metric, or in the server-side CAPI integration. A merchant who ports a Script to a Function and does not verify the downstream event payload against a set of representative test carts will not catch most of these until an attribution report or a Meta ad-optimization signal starts drifting.
Shopify Functions are available on all tiers, but certain capability scopes are reserved for Plus tenants. The Plus-elevated scopes that most affect tracking: (1) blocking-mode checkout validation (blocking the Continue button until validation resolves, which affects event timing); (2) elevated data access in delivery customization Functions that need to read shipping-carrier rate tables; (3) elevated capability on payment customization Functions that need to gate payment methods based on B2B or Multi-Origin tenant configuration; and (4) integration with Plus-tier Checkout UI Extensions that render at checkout points not exposed to standard-tier Extensions. Merchants running any of these Plus-elevated Function scopes should treat the corresponding customer-event surface as Plus-specific for scan and monitoring purposes.
Shopify Flow is a workflow automation tool that consumes customer events (and other Shopify events) as triggers and can invoke actions in response. Flow is not a substitute for Functions and vice versa: Functions modify checkout state during the customer flow, Flow reacts to Shopify events after the fact. A common pattern is a Function that applies a bundle discount at checkout, followed by a Flow triggered on order-created that tags the customer for a Klaviyo follow-up campaign referencing the bundle purchase. Both are Shopify-native, both compose cleanly, and both surface event data to downstream integrations, but they operate on different sides of the customer-event fire.
The pre-ship test discipline that catches most Script-to-Function port bugs: (1) build a representative test-cart matrix (single-item, multi-item, bundle, discounted, cross-currency if Multi-Origin) with expected pre-Function and post-Function totals; (2) run each cart through the Function in the Shopify CLI local development environment and compare the transformed cart state against expectations; (3) deploy to a Shopify staging tenant and run each cart through a real Checkout Extensibility flow to observe the customer-event payload; (4) verify the Meta Pixel or Custom Pixel event received against expectations, including value, currency, line_items, and any custom event fields; (5) verify server-side CAPI event received against Meta Events Manager Test Events surface if the merchant runs CAPI; (6) verify Klaviyo Placed Order metric received against the Klaviyo metric-inspector surface. Only after all six pass on the representative test-cart matrix should the Function ship to production.
PixelProof runs its scan against the customer-facing storefront and observes what registered pixels (Meta Pixel via the sales-channel app, Klaviyo via the Klaviyo app, or a Custom Pixel installed via the admin) actually receive during a customer traversal. On a Function-active tenant, the scan observes the post-Function event payload exactly as any external pixel does. If a Function is producing a bad payload, the scan will show that bad payload in the reported Meta Pixel event data. What the scan does not do is directly introspect the Function source code (that lives in the merchant admin as a Shopify app extension) or the Shopify Flow workflow definitions (those live in the merchant admin Flow surface); the scan is a downstream observer, not an internal-surface auditor.
For a Plus tenant that shipped a Script-to-Function port in the Aug 26, 2026 migration window, the scan is a fast way to verify that customer-event payloads on the migrated checkout still match the pre-migration expectations. For an ongoing tenant, the scan schedule catches Function-related regressions when a subsequent Function deploy changes the payload in ways the merchant did not anticipate. The paid tier (see the pricing page) runs scheduled scans and alerts on payload drift.
For the broader Plus vs standard tracking-surface comparison, see Shopify Plus Tracking Differences vs Standard Shopify (2026). For the Shopify 2.0 customer event catalog end-to-end, see Shopify 2.0 Tracking Events Guide (2026). For the Meta Conversions API server-side setup that consumes Function-affected order data, see Meta Conversions API Setup for Shopify (2026 Deep Dive). For the six-tool honest listicle of the broader Shopify pixel-monitoring category, see Best Shopify Pixel Monitoring Tools 2026.
Shopify Scripts were Ruby-based checkout customization scripts available exclusively on Shopify Plus tenants. They ran on Shopify infrastructure during the checkout flow and could apply discounts, alter line items, gate shipping options, and modify payment gateway behavior on a per-checkout basis. Shopify Functions are the WebAssembly-based replacement: developer-authored code compiled to Wasm, deployed as a Shopify app extension, and executed on Shopify infrastructure at defined checkout targets. Functions are available on all tiers for the base runtime, with elevated capability scopes retained on Plus. The functional overlap is intentional: Functions cover the customization use cases Scripts served, plus additional targets Scripts never had access to.
The Aug 26, 2026 Checkout Extensibility deadline retired the legacy checkout.liquid template on Plus stores that had not migrated. Alongside the checkout.liquid retirement, Shopify Scripts as previously deployed on that legacy checkout surface stopped running on stores using the migrated Checkout Extensibility flow. Plus tenants had to re-implement any Script-based logic as Shopify Functions running against the Checkout Extensibility targets. For a Plus tenant that had customized their checkout with Scripts driving discount logic, line-item bundling, or payment-method gating, that logic ceased to function on the migrated checkout unless it was ported to Shopify Functions ahead of the migration date.
Shopify officially deprecated the Scripts API and stopped accepting new Script installations well before Aug 26, 2026. Existing Scripts on stores still on the legacy checkout continued to function through the deadline. Any new checkout-customization work today is written against Shopify Functions targets, not against Scripts. If a merchant needs a customization pattern their old Script provided, the port target is a Shopify Function running against the equivalent Checkout Extensibility target.
Neither Scripts nor Functions is directly a tracking surface. Scripts modified checkout state (discounts, line items, shipping options, payment methods). Functions modify checkout state at defined targets (cart transform, delivery customization, payment customization, discount, checkout validation). The Meta Pixel does not read Script or Function output directly; it reads the resulting checkout state through the Shopify Web Pixels API customer-event catalog. What Scripts or Functions do influence indirectly is the event payload: a Function that transforms the cart affects the line_items array in the subsequent checkout_started event, and a Function that gates payment methods affects the payment_info_submitted event.
The Meta Pixel runs through the Web Pixels API sandbox, in a separate execution context from Shopify Functions. Functions execute on Shopify infrastructure server-side, before the customer event is emitted to the customer-event catalog. The Meta Pixel receives the resulting event with whatever cart, discount, and payment state the Functions produced. This ordering matters for attribution correctness: a Function that applies a cart-transform discount will emit the checkout_completed event with the discounted total, and the Meta Pixel purchase event fires with that discounted value. If the merchant needs to send the pre-discount value, the merchant must configure that transformation in their Custom Pixel or in their server-side Conversions API integration.
Four targets most directly affect Meta Pixel and Klaviyo event payloads: (1) cart transform, which changes line-item composition and price; (2) discount, which applies programmatic discount logic; (3) delivery customization, which changes shipping options and pricing; (4) checkout validation, which can block the checkout Continue button and change the ordering of events. Merchants deploying Functions in any of these targets should verify that the downstream customer-event payload still matches their attribution expectations, both in browser events (via the Web Pixels API-registered pixels) and in server events (via the merchant Conversions API integration).
No. Shopify Functions run in a defined server-side execution model with input scoped to the target (cart, delivery options, discount context, validation context, payment context). Functions do not have access to the customer-event stream itself and cannot read events fired to registered pixels. The event stream is a downstream consumer of the checkout state Functions produce, not an input to Functions. Merchants who want to react to customer events downstream do so in their Custom Pixels, in their server-side integrations, or in Shopify Flow with the customer-event trigger.
PixelProof runs its scan against the customer-facing storefront and observes what the Meta Pixel and other registered pixels actually receive during a customer traversal. The scan detects the resulting event payload, dedup health, and consent-gating on any customer traversal, regardless of whether Functions were involved in producing that state. What PixelProof does not do is introspect the merchant's Function code directly (that lives in the merchant admin as a Shopify app extension). Merchants who want internal-surface Function change visibility get that from the Shopify developer changelog and their own git repo for the Function source; PixelProof covers the downstream storefront and checkout side of the same story.
Just ported a Script to a Function? Scan the migrated checkout and verify the customer-event payload still matches pre-migration expectations.