### Install Address Autocomplete Source: https://shopify.dev/docs/apps/build/checkout/delivery-shipping/address-autocomplete/address-autocomplete Install the Address Autocomplete library using npm or yarn. ```bash npm install @shopify/address-autocomplete # or yarn add @shopify/address-autocomplete ``` -------------------------------- ### Post-Purchase UI Extension Setup Source: https://shopify.dev/docs/apps/build/checkout/product-offers/create-a-post-purchase-subscription This snippet demonstrates the initial setup for a post-purchase UI extension. It includes fetching offer data from an app server and rendering a callout banner to the buyer. ```typescript import { extend, BlockStack, Button, CalloutBanner, Heading, Image, Text, TextContainer, Separator, Tiles, TextBlock, Layout, BuyerConsent, Select, } from "@shopify/post-purchase-ui-extensions"; // For local development, replace APP_URL with your local tunnel URL. const APP_URL = "https://abcd-1234.trycloudflare.com"; // Preload data from your app server to ensure the extension loads quickly. extend( "Checkout::PostPurchase::ShouldRender", async ({ inputData, storage }) => { const postPurchaseOffer = await fetch(`${APP_URL}/api/offer`, { method: "POST", headers: { Authorization: `Bearer ${inputData.token}`, "Content-Type": "application/json", }, body: JSON.stringify({ referenceId: inputData.initialPurchase.referenceId, }), }).then((response) => response.json()); await storage.update(postPurchaseOffer); // For local development, always show the post-purchase page return { render: true }; } ); extend( "Checkout::PostPurchase::Render", (root, { done, storage, calculateChangeset, applyChangeset, inputData }) => { const { offers } = storage.initialData; // Track the buyer's approval to the subscriptions policies. let buyerConsent = false; let selectedPurchaseOption = 0; const purchaseOptions = offers; const purchaseOption = purchaseOptions[selectedPurchaseOption]; const calloutBannerComponent = root.createComponent( CalloutBanner, { title: "It's not too late to add this to your order." }, [ root.createComponent( Text, { size: "medium" }, `Add the ${purchaseOption.productTitle} to your order and ` ), root.createComponent( Text, { size: "medium", emphasized: true }, "save 15%." ), ] ); ``` -------------------------------- ### Checkout UI Extension Configuration Example Source: https://shopify.dev/docs/apps/build/checkout/fields-banners/add-banner?extension=polaris Example of how to define targets for your checkout UI extension in the `shopify.extension.toml` file. Multiple targets can be specified for different rendering locations. ```toml [extensions.targeting] module = "@Checkout/Checkout.jsx" target = "customer_card" ``` -------------------------------- ### Install Dependencies with npm Source: https://shopify.dev/docs/apps/build/checkout/product-offers/build-a-post-purchase-offer Install the jsonwebtoken and uuid packages using npm. These are required for the app server within the extension directory. ```bash npm install jsonwebtoken uuid ``` -------------------------------- ### Checkout UI Extension Configuration Example Source: https://shopify.dev/docs/apps/build/checkout/fields-banners/add-banner Example of how to configure targets for a checkout UI extension in the shopify.extension.toml file. Multiple targets can be defined to render the extension in different checkout locations. ```toml [extensions.targeting] module = "@my-checkout-ui-extension/main" target = "customer_ অ্যাকাউন্ট.contact_information" ``` -------------------------------- ### Start Shopify CLI Dev Preview Source: https://shopify.dev/docs/apps/build/checkout/cart-checkout-validation/create-server-side-validation-function Use the Shopify CLI `dev` command to start the dev preview for your app. This command keeps the preview running and automatically rebuilds your function when changes are detected. ```bash cd ../.. shopify app dev ``` -------------------------------- ### Install Dependencies with pnpm Source: https://shopify.dev/docs/apps/build/checkout/product-offers/build-a-post-purchase-offer Install the jsonwebtoken and uuid packages using pnpm. These are required for the app server within the extension directory. ```bash pnpm add jsonwebtoken uuid ``` -------------------------------- ### Example JSON Response for Configurations Source: https://shopify.dev/docs/apps/build/checkout/styling/use-graphiql-app This is an example JSON response showing the structure of checkout and accounts configurations, including the node ID and published status. It's used to identify the correct configuration ID. ```json { "data": { "checkoutAndAccountsConfigurations": { "edges": [ { "node": { "id": "gid://shopify/CheckoutAndAccountsConfiguration/123456789", "isPublished": true } } ] } } } ``` -------------------------------- ### Example GraphQL Response for Product Data Source: https://shopify.dev/docs/apps/build/checkout/product-offers/build-a-post-purchase-offer This is an example JSON response when querying for product data. It includes details like product ID, title, description, and variant information. ```json { "data": { "products": { "edges": [ { "node": { "id": "gid://shopify/Product/123456789", "legacyResourceId": "123456789", "title": "The S-Series Snowboard", "featuredMedia": { "preview": { "image": { "url": "https://cdn.shopify.com/s/files/1/123" } } }, "description": "This PREMIUM snowboard is so SUPERDUPER awesome!", "variants": { "edges": [ { "node": { "price": "699.95", "compareAtPrice": null, "id": "gid://shopify/ProductVariant/987654321", "legacyResourceId": "987654321" } } ] } } } ] } } } } ``` -------------------------------- ### Install Dependencies with Yarn Source: https://shopify.dev/docs/apps/build/checkout/product-offers/build-a-post-purchase-offer Install the jsonwebtoken and uuid packages using Yarn. These are required for the app server within the extension directory. ```bash yarn add jsonwebtoken uuid ``` -------------------------------- ### Navigate to Extension Directory Source: https://shopify.dev/docs/apps/build/checkout/delivery-shipping/delivery-methods/create-local-pickup-charges-function After generating the extension, navigate to its directory to start modifying its files. ```bash cd extensions/local-pickup-generator ``` -------------------------------- ### Example JSON Response for Color Scheme Update Source: https://shopify.dev/docs/apps/build/checkout/styling/update-color-settings This is an example of a successful JSON response after applying a color scheme update mutation. It confirms the applied color scheme and shows an empty userErrors array. ```json { "data": { "checkoutBrandingUpsert": { "checkoutBranding": { "customizations": { "orderSummary": { "colorScheme": "COLOR_SCHEME1" } } }, "userErrors": [] } }, "extensions": { "cost": { "requestedQueryCost": 12, "actualQueryCost": 12 } } } ``` -------------------------------- ### Configure Multiple Targets in shopify.extension.toml Source: https://shopify.dev/docs/apps/build/checkout/customize-footer?extension=polaris Define multiple targets in your `shopify.extension.toml` file to specify where your extension should render. This example configures the extension for both the checkout and thank you footers. ```toml [extensions.targeting] module = "./src/Checkout.jsx" target = "purchase.checkout.footer.render-after" [[extensions.targeting]] module = "./src/ThankYou.jsx" target = "purchase.thank-you.footer.render-after" ``` -------------------------------- ### Example JSON Response for File Creation Source: https://shopify.dev/docs/apps/build/checkout/styling/add-favicon The response from the `fileCreate` mutation includes the `id` of the created file, which is essential for applying the image as a favicon. ```json { "data": { "fileCreate": { "files": [ { "id": "gid://shopify/MediaImage/34829967327254", "alt": "Our logo, a leaf from the Monstera Deliciosa plant", "filename": "favicon-image", "createdAt": "2023-11-107T02:44:06Z" } ] } }, } ``` -------------------------------- ### Build a Rust function for Shopify Source: https://shopify.dev/docs/apps/build/checkout/delivery-shipping/delivery-methods/create-local-pickup-charges-function Use this command to build your Rust function for the `wasm32-unknown-unknown` target. Ensure Rust and the target are installed. ```bash cargo build --target=wasm32-unknown-unknown --release ``` -------------------------------- ### Example Checkout Profile ID Response Source: https://shopify.dev/docs/apps/build/checkout/styling/customize-form-controls This is an example JSON response when querying for the published checkout profile ID. ```json { "data": { "checkoutProfiles": { "edges": [ { "node": { "id": "gid://shopify/CheckoutProfile/1", "name": "Default checkout profile" } } ] } } } ``` -------------------------------- ### Initialize Payment Customizations Sample App Source: https://shopify.dev/docs/apps/build/checkout/payments Use this command to clone the payment customizations sample app to your local environment. Follow the prompts to name your project. ```bash shopify app init --template https://github.com/Shopify/function-examples/sample-apps/payment-customizations ``` -------------------------------- ### Initialize Delivery Customizations Sample App Source: https://shopify.dev/docs/apps/build/checkout/delivery-shipping/delivery-options/build-function Initialize the delivery customizations sample app using the Shopify CLI. This command clones the sample app repository and sets up a new project. ```bash shopify app init --template https://github.com/Shopify/function-examples/sample-apps/delivery-customizations ``` -------------------------------- ### Create and Release App Version Source: https://shopify.dev/docs/apps/build/checkout/customize-header?extension=polaris Navigate to your app directory and run this command to create and release a new app version, which is a snapshot of your app configuration and extensions. ```bash shopify app version ``` -------------------------------- ### Generate Post-Purchase UI Extension Source: https://shopify.dev/docs/apps/build/checkout/product-offers/build-a-post-purchase-offer Use Shopify CLI to generate starter code for a new post-purchase UI extension. This command creates the necessary directory structure and initial files. ```bash shopify app generate extension --template post_purchase_ui --name my-post-purchase-ui-extension ``` -------------------------------- ### Deploy App Version Source: https://shopify.dev/docs/apps/build/checkout/delivery-shipping/address-autocomplete/address-autocomplete Run this command in your app directory to create a new version of your app. This version can then be released to users. You can optionally provide a name and message for the version. ```bash shopify app deploy ``` -------------------------------- ### Example Checkout Profile Response Source: https://shopify.dev/docs/apps/build/checkout/styling This is an example JSON response when querying for checkout profiles, showing the ID and name of a default profile. ```json { "data": { "checkoutProfiles": { "edges": [ { "node": { "id": "gid://shopify/CheckoutProfile/1", "name": "Default checkout profile" } } ] } } } ``` -------------------------------- ### Build Post-Purchase Subscription UI Components Source: https://shopify.dev/docs/apps/build/checkout/product-offers/create-a-post-purchase-subscription This snippet shows how to construct the UI for a post-purchase subscription offer. It includes creating text blocks, buttons, price breakdowns, and product information components. ```javascript const productDescriptionTextBlocks = purchaseOption.productDescription.map( (text) => root.createComponent(TextBlock, { subdued: true }, text) ); const productDescriptionComponent = root.createComponent( BlockStack, { spacing: "xtight" }, productDescriptionTextBlocks ); const acceptButtonText = root.createText(""); const acceptButton = root.createComponent( Button, { onPress: acceptOffer, submit: true, disabled: true, loading: true, }, acceptButtonText ); const declineButton = root.createComponent( Button, { onPress: declineOffer, subdued: true }, "Decline this offer" ); const buttonsComponent = root.createComponent(BlockStack, {}, [ acceptButton, declineButton, ]); const subtotalAmount = root.createText(""); const shippingAmount = root.createText(""); const taxesAmount = root.createText(""); const totalAmount = root.createText(""); const originalPriceAmount = root.createText(""); const discountedPriceAmount = root.createText(""); const priceBreakdownComponent = root.createComponent( BlockStack, { spacing: "tight" }, [ root.createComponent(Separator), createPriceBreakdownLine({ label: "Subtotal", amount: subtotalAmount, }), createPriceBreakdownLine({ label: "Shipping", amount: shippingAmount, }), createPriceBreakdownLine({ label: "Taxes", amount: taxesAmount, }), root.createComponent(Separator), createMoneySummary({ label: "Total", amount: totalAmount }), ] ); const originalPriceHeader = root.createComponent( Text, { role: "deletion", size: "large" }, originalPriceAmount ); const discountedPriceHeader = root.createComponent( Text, { emphasized: true, size: "large", appearance: "critical" }, discountedPriceAmount ); const priceHeaderComponent = root.createComponent( TextContainer, { alignment: "leading", spacing: "loose" }, [originalPriceHeader, " ", discountedPriceHeader] ); const wrapperComponent = root.createComponent(BlockStack, {}, [ root.createComponent(Heading, {}, purchaseOption.productTitle), priceHeaderComponent, productDescriptionComponent, priceBreakdownComponent, buttonsComponent, ]); const buyerConsentComponent = root.createComponent(BuyerConsent, { policy: "subscriptions", checked: buyerConsent, onChange: () => { buyerConsent = !buyerConsent; }, }); function createPriceBreakdownLine({ label, amount, textSize = "small" }) { return root.createComponent(Tiles, {}, [ root.createComponent(TextBlock, { size: "small" }, label), root.createComponent( TextContainer, { alignment: "trailing" }, root.createComponent( TextBlock, { emphasized: true, size: textSize }, amount ) ), ]); } function createMoneySummary({ label, amount }) { return root.createComponent(Tiles, {}, [ root.createComponent( TextBlock, { emphasized: true, size: "medium" }, label ), root.createComponent( TextContainer, { alignment: "trailing" }, root.createComponent( TextBlock, { emphasized: true, size: "medium" }, amount ) ), ]); } const purchaseOptionSelect = root.createComponent(Select, { label: "Purchase options", value: selectedPurchaseOption.toString(), options: purchaseOptions.map((option, index) => ({ label: option.title, value: index.toString(), })), onChange: (value) => { const previousPurchaseOption = purchaseOptions[selectedPurchaseOption]; selectedPurchaseOption = parseInt(value, 10); updatePriceBreakdownUI(previousPurchaseOption); }, }); if (purchaseOptions.length > 1) { wrapperComponent.insertChildBefore( purchaseOptionSelect, priceBreakdownComponent ); } // Get shipping costs and taxes and update the UI async function updatePriceBreakdownUI(previousPurchaseOption) { const currentPurchaseOption = purchaseOptions[selectedPurchaseOption]; acceptButton.updateProps({ loading: true }); // Request shopify to calculate shipping costs and taxes for the upsell const result = await calculateChangeset({ changes: purchaseOptions[selectedPurchaseOption].changes, }); ``` -------------------------------- ### Accept Post-Purchase Offer (Vanilla JS) Source: https://shopify.dev/docs/apps/build/checkout/product-offers/build-a-post-purchase-offer This snippet demonstrates how to accept a post-purchase offer using Vanilla JavaScript. It includes updating button states before making the request to sign and apply the changeset. ```javascript async function acceptOffer() { async function doAcceptOrder() { // Make a request to your app server to sign the changeset with your app's API secret key. const token = await fetch(`${APP_URL}/api/sign-changeset`, { method: "POST", headers: { Authorization: `Bearer ${inputData.token}`, "Content-Type": "application/json", }, body: JSON.stringify({ referenceId: inputData.initialPurchase.referenceId, changes: id, }), }) .then((response) => response.json()) .then((response) => response.token) .catch((e) => console.log(e)); // Make a request to Shopify servers to apply the changeset. await applyChangeset(token); } // First update the state of the buttons, then call the async function. acceptButton.updateProps({ disabled: true, loading: true }); declineButton.updateProps({ disabled: true }); await doAcceptOrder(); done(); } ``` -------------------------------- ### Handle Address Selection Source: https://shopify.dev/docs/apps/build/checkout/delivery-shipping/address-autocomplete/address-autocomplete Listen for the 'address-select' event to get the selected address details. ```javascript addressAutofill.on('address-select', (event) => { console.log(event.detail.address); }); ``` -------------------------------- ### Navigate to App Directory Source: https://shopify.dev/docs/apps/build/checkout/customize-header Navigate to your app's directory before generating a new extension. ```bash cd ``` -------------------------------- ### Default Locale Example Source: https://shopify.dev/docs/apps/build/checkout/localized-checkout-ui-extensions Insert `.default` between the locale and the `.json` file extension to designate a default locale. ```json en-CA.default.json ``` -------------------------------- ### Applying Multiple Changes in Parallel Source: https://shopify.dev/docs/apps/build/checkout/extension-performance/applying-changes This example illustrates how to apply multiple changes concurrently using `Promise.all`. This approach is recommended for efficiency, reducing latency, and avoiding rate limits when several updates are needed. ```javascript const results = await Promise.all([ shopify.applyMetafieldChange({ type: 'updateCartMetafield', metafield: { namespace: '$app:preferences', key: 'shipping-region', type: 'single_line_text_field', value: region, }, }), shopify.applyCartLinesChange({ type: 'updateCartLines', lines: [ { id: cartLineId, quantity: 1, attributes: { key: 'discount-code', value: discountCode, }, }, ], }), ]); ``` -------------------------------- ### Accepting and Declining Post-Purchase Offers Source: https://shopify.dev/docs/apps/build/checkout/product-offers/build-a-post-purchase-offer This snippet shows the logic for accepting an offer by signing a changeset and applying it, or declining the offer. It includes UI components for displaying the offer details and buttons for user interaction. ```javascript function acceptOffer() { setLoading(true); // Make a request to your app server to sign the changeset with your app's API secret key. const token = await fetch(`${APP_URL}/api/sign-changeset`, { method: "POST", headers: { Authorization: `Bearer ${inputData.token}`, "Content-Type": "application/json", }, body: JSON.stringify({ referenceId: inputData.initialPurchase.referenceId, changes: purchaseOption.id, }), }) .then((response) => response.json()) .then((response) => response.token) .catch((e) => console.log(e)); // Make a request to Shopify servers to apply the changeset. await applyChangeset(token); // Redirect to the thank-you page. done(); } function declineOffer() { setLoading(true); // Redirect to the thank-you page done(); } return ( It's not too late to add this to your order Add the {purchaseOption.productTitle} to your order and{" "} {purchaseOption.changes[0].discount.title} {purchaseOption.productTitle} ); } ``` -------------------------------- ### JSON Response for Checkout Branding Source: https://shopify.dev/docs/apps/build/checkout/styling/customize-typography This is an example of a successful JSON response after applying a Shopify font to the checkout branding. ```json { "data": { "checkoutBrandingUpsert": { "checkoutBranding": { "designSystem": { "typography": { "primary": { "base": { "sources": "local('Assistant Regular'), local('Assistant-Regular'), url(https://fonts.shopifycdn.com/assistant/assistant_n4.bcd3d09dcb631dec5544b8fb7b154ff234a44630.woff2?valid_until=MTY5OTM4MjI4Mw&hmac=407320ad74949088a8cbb72b20ec57fb0db385f085d671613b87fa52d7b77e65) format('woff2'),url(https://fonts.shopifycdn.com/assistant/assistant_n4.a2d012304becc2a26f1ded1acc136fcab85c9afd.woff?valid_until=MTY5OTM4MjI4Mw&hmac=f25fd27b446cd50eee14c14a67253f2d4deedaee34eb21ed6569da87118c5335) format('woff')" } } } } }, "userErrors": [] } } } } ``` -------------------------------- ### Scaffold a new Shopify app Source: https://shopify.dev/docs/apps/build/checkout/start-building Initializes a new Shopify app project with the necessary boilerplate code. ```bash shopify app init ``` -------------------------------- ### English Pluralization Example Source: https://shopify.dev/docs/apps/build/checkout/localized-checkout-ui-extensions Defines pluralization keys for English, supporting 'one' for singular and 'other' for plural forms. ```json { "youHaveMessages": { "one": "you have one message", "other": "you have {{count}} messages" } } ``` -------------------------------- ### Regional Locale Example Source: https://shopify.dev/docs/apps/build/checkout/localized-checkout-ui-extensions Append an ISO 3166-1 region code after the language tag to specify a regional locale. ```json en-CA.json ``` -------------------------------- ### Open Dev Console and Preview Custom Header Extension Source: https://shopify.dev/docs/apps/build/checkout/customize-header?extension=polaris Steps to open the Dev Console and preview your custom header extension. ```bash shopify app dev ``` -------------------------------- ### Get Billing Interval Helper Source: https://shopify.dev/docs/apps/build/checkout/product-offers/create-a-post-purchase-subscription Converts billing interval codes (e.g., 'DAY', 'MONTH') into human-readable strings. ```javascript function getBillingInterval(interval) { switch (interval) { case "DAY": return "every day"; case "WEEK": return "every week"; case "MONTH": return "every month"; case "YEAR": return "every year"; } } ``` -------------------------------- ### Get Checkout Profiles Source: https://shopify.dev/docs/apps/build/checkout/styling/add-favicon Retrieves a list of checkout profiles, which can be used to identify the ID for subsequent branding mutations. ```APIDOC ## POST https://{shop}.myshopify.com/api/{api_version}/graphql.json ### Description Retrieves checkout profiles, allowing you to find the ID for a specific profile. ### Method POST ### Endpoint https://{shop}.myshopify.com/api/{api_version}/graphql.json ### Query ```graphql query checkoutProfiles { checkoutProfiles(first: 1, query: "is_published:true") { edges { node { id name } } } } ``` ### Response Example ```json { "data": { "checkoutProfiles": { "edges": [ { "node": { "id": "gid://shopify/CheckoutProfile/1", "name": "Default checkout profile" } } ] } } } ``` ``` -------------------------------- ### Deploy Extension with Source Maps Source: https://shopify.dev/docs/apps/build/checkout/test-checkout-ui-extensions Use the `app deploy` command with the `verbose` flag to generate source maps for your extension. The command output will indicate the location of the generated source map file within your extension's project directory, typically in a `dist` folder. ```bash shopify app deploy --verbose ``` -------------------------------- ### JSON Response for Checkout Branding Source: https://shopify.dev/docs/apps/build/checkout/styling/customize-sections This is an example of a JSON response after successfully updating checkout branding. It confirms the applied color scheme. ```json { "data": { "checkoutBrandingUpsert": { "checkoutBranding": { "designSystem": { "colors": { "schemes": { "scheme3": { "base": { "background": "#f7faf5", "text": "#44691e", "border": "#dce9d3", "icon": "#44691e", "accent": "#44691e", "decorative": "#44691e" }, "control": { "background": "#f7faf5" } } } } } } } } ``` -------------------------------- ### Check App Information Source: https://shopify.dev/docs/apps/build/checkout/customize-header?extension=polaris Verify your app's organization and development store details using this command. ```bash shopify app info ``` -------------------------------- ### Build Validation Function for WASM Source: https://shopify.dev/docs/apps/build/checkout/cart-checkout-validation/create-admin-ui-validation Builds the validation function targeting the wasm32-wasip1 platform for release. Ensure Rust and the necessary WASI target are installed. ```bash cargo build --target=wasm32-wasip1 --release ``` -------------------------------- ### Create a Checkout UI Extension with Shopify CLI Source: https://shopify.dev/docs/apps/build/checkout/customize-header?extension=polaris Use this command to generate a new checkout UI extension. It sets up the basic file structure and boilerplate code for your extension. ```bash shopify app generate extension --template checkout_ui --name my-checkout-ui-extension ``` -------------------------------- ### Source Map File Structure Example Source: https://shopify.dev/docs/apps/build/checkout/test-checkout-ui-extensions This structure illustrates the typical location and naming convention of a source map file generated for a Shopify extension. The `dist` folder contains the hashed JavaScript bundle and its corresponding source map. ```text 9 1 2 3 4 {extension-type}-sandbox-{app-name}-{target}-{extension-id}-{unique-ID} └─ extensions.shopifycdn.com └─ partners-extensions-scripts-bucket/ui-extension/handle/{name_of_extension}... └─ {filename_hash}.js ```