Shopify Function Examples

repository·main·Indexed 42 days ago

https://github.com/shopify/function-examples

A collection of public Shopify Function examples used by the Shopify CLI during extension generation. This reference provides implementation guides for various Shopify Functions across different languages, including Rust and JavaScript, covering use cases such as discounts, order routing, and pickup point delivery option generators.

Tokens
21.4K
Snippets
77
Records
113
Agent score
52%

What's inside Shopify Function Examples

  1. How Pickup Point Delivery Option Generators work

    main

    This function demonstrates how to generate pickup point delivery options by fetching data from an external API via an HTTP request. The implementation is split into two distinct targets:

    1. Fetch target: Responsible for generating the HTTP request. It takes input (like delivery address country and coordinates) and outputs a FunctionFetchResult containing the request details (method, URL, headers, etc.).
    2. Run target: Responsible for processing the API response. It takes the fetchResult (status and body) and produces the final pickup point data in the format specified by FunctionRunResult.

    This two-step process allows the function to bridge external data sources with Shopify's delivery option generation logic.

    // The function uses two targets:
    // 1. Fetch target (src/fetch.rs) -> generates HTTP request
    // 2. Run target (src/run.rs) -> parses response and produces pickup points
  2. Configure Expand Bundle functionality via metafields

    main

    To enable the Expand bundle operation, the bundle's parent product_variant must have two specific metafields:

    1. component_reference

      • Namespace: custom
      • Key: component_reference
      • Content Type: variants
      • Value: An array of product_variant GIDs.
    2. component_quantities

      • Namespace: custom
      • Key: component_quantities
      • Content Type: integer
      • Value: An array of integers corresponding to the quantities of the variants in component_reference.

    Example Configuration: For a bundle containing two shirts (ID 3) and one pair of pants (ID 4):

    • component_reference: ["gid://shopify/ProductVariant/3", "gid://shopify/ProductVariant/4"]
    • component_quantities: [2, 1]
    // component_reference
    [
      "gid://shopify/ProductVariant/3",
      "gid://shopify/ProductVariant/4"
    ]
    
    // component_quantities
    [2, 1]
  3. How to make a non-embedded Shopify app

    main

    By default, this template is configured as an embedded app. To run it as a non-embedded app, perform these three steps:

    1. Remove the <script/> tag for App Bridge in /app/routes/app.jsx.
    2. Remove any usage of App Bridge APIs (window.shopify) from your code.
    3. Update the shopifyApp configuration in app/shopify.server.js by passing isEmbeddedApp: false.
  4. Configure Merge Bundle functionality via `component_parents` metafield

    main

    To enable the Merge bundle operation, each child component belonging to a bundle must have a metafield with the following properties:

    • Namespace: custom
    • Key: component_parents
    • Content Type: JSON

    The value of this metafield must be an array of objects. Each object defines a bundle rule that links the child to a parent variant.

    Bundle Rule Schema:

    {
      "id": <Bundle parent ProductVariant ID>,
      "component_reference": {
        "value": <Array of Bundle children ProductVariant IDs>
      },
      "component_quantities": {
        "value": <Array of quantities for children ProductVariant IDs>
      }
    }

    Important Requirements:

    1. ID Format: All IDs must be Shopify product_variant GIDs (e.g., gid://shopify/ProductVariant/6).
    2. Ordering: The order of IDs in component_reference must match the order of quantities in component_quantities.
    3. Completeness: The merge operation only triggers if the extension detects all components of a given bundle in the cart at checkout.
    [
      {
        "id": "gid://shopify/ProductVariant/6",
        "component_reference": {
          "value": [
            "gid://shopify/ProductVariant/3",
            "gid://shopify/ProductVariant/4"
          ]
        },
        "component_quantities": {
          "value": [2, 1]
        }
      }
    ]
  5. How the `cart-merge-expand` extension works

    main

    The cart-merge-expand extension utilizes the Shopify cart_transform function to perform two types of transformations in the cart: Merge bundle and Expand bundle.

    • Merge bundle: Detects individual components in the cart that belong to a specific bundle and combines them into a single parent_product_variant representation.
    • Expand bundle: Detects a single bundle product and expands it into its constituent product_variants.

    Both operations rely on specific Shopify metafields defined on product_variant objects to determine bundle rules and relationships.

  6. Manage webhooks using app-specific subscriptions

    main

    To avoid issues with webhook synchronization and HMAC validation, use app-specific webhooks defined in your shopify.app.toml file instead of registering shop-specific webhooks in the afterAuth hook.

    Benefits of app-specific webhooks:

    • Automatic Sync: Shopify automatically syncs changes every time you run deploy.
    • HMAC Validation: Webhooks created in the Shopify Admin will fail HMAC validation because they aren't signed with your app's secret. App-specific webhooks avoid this.

    Troubleshooting shop-specific webhooks:

    If you must use shop-specific webhooks via afterAuth, remember that afterAuth only triggers during app installation or when an access token expires. To force an update during development, you must uninstall and reinstall the app.

  7. Configure MongoDB with Prisma

    main

    This template uses SQLite by default. If you switch to MongoDB, you must adjust your Prisma schema and configuration because MongoDB does not support prisma migrate.

    Mapping the ID field

    Prisma expects the ID field to be the ID of the session, not the MongoDB _id field. You must map the _id field to a new session_id field in your schema:

    model Session {
      session_id  String    @id @default(auto()) @map("_id") @db.ObjectId
      id          String    @unique
      ...
    }

    Using db push instead of migrate

    Since MongoDB doesn't support prisma migrate, use prisma db push. Update your shopify.web.toml file to include these commands:

    [commands]
    predev = "npx prisma generate && npx prisma db push"
    dev = "npx prisma migrate deploy && npm exec react-router dev"

    Requirement: Replica Set

    To perform transactions, your MongoDB server must be running as a replica set.

  8. Start local development for your Shopify app

    main

    After installing the template, use the Shopify CLI to connect to your app in the Partners dashboard. The CLI manages environment variables and runs commands in parallel.

    Run the development command from the root of your app directory using your preferred package manager. Once the command runs, open the URL generated in your console and grant the necessary permissions to begin development (e.g., generating extensions).

    # Using yarn
    yarn dev
    
    # Using npm
    npm run dev
    
    # Using pnpm
    pnpm run dev
  9. How to Build a Bundle using Cart Transform

    main

    To implement bundling using the cart_transform function in this sample app, you must configure specific metafields on product variants to define the relationship between a 'parent' bundle variant and its 'child' component variants.

    1. Configure Variant Metafield Definitions

    Create the following three metafield definitions under Settings > Custom data > Variants:

    NameNamespace and keyType
    component_referencecustom.component_referenceProduct Variant (List of product variants)
    component_quantitiescustom.component_quantitiesInteger (List of values, Min: 1)
    component_parentscustom.component_parentsJSON

    JSON Schema for custom.component_parents:

    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "title": "Bundle component parents",
      "description": "A definition of the bundle a child belongs to",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "description": "ID of bundle parent product variant: gid://shopify/ProductVariant/<id number>",
            "type": "string"
          },
          "component_reference": {
            "type": "object",
            "properties": {
              "value": {
                "description": "Array of product variant IDs: [gid://shopify/ProductVariant/<id number>]",
                "type": "array",
                "items": {
                  "type": "string"
                },
                "minItems": 1,
                "uniqueItems": true
              }
            },
            "required": ["value"]
          },
          "component_quantities": {
            "type": "object",
            "properties": {
              "value": {
                "description": "Array of quantities of product variants defined in component_reference: [1]",
                "type": "array",
                "items": {
                  "type": "integer"
                },
                "minItems": 1
              }
            },
            "required": ["value"]
          },
          "price_adjustment": {
            "type": "object",
            "properties": {
              "value": {
                "description": "Array of quantities of product variants defined in component_reference: [1]",
                "type": "array",
                "items": {
                  "type": "number",
                  "minimum": 0
                }
              }
            },
            "required": ["value"]
          }
        },
        "required": ["id", "component_reference", "component_quantities"]
      }
    }

    2. Define the Bundle Parent

    1. Create a product to act as the bundle. It must have at least one variant in inventory, a price > 0, and at least one option.
    2. On the Parent Product Variant page, locate the Metafields section.
    3. Set custom.component_reference by selecting the product variants that will be included in the bundle.
    4. Set custom.component_quantities by entering quantities that correspond to the order of variants in component_reference.
    5. Note the Parent Variant ID from the browser URL (e.g., gid://shopify/ProductVariant/<id>).

    3. Define the Bundle on Child Variants

    For each child variant included in the bundle, you must update its custom.component_parents metafield with a JSON array matching the parent's configuration:

    [
      {
        "id": "gid://shopify/ProductVariant/<ID of parent product variant>",
        "component_reference": {
          "value": [
            "gid://shopify/ProductVariant/<ID of first child product variant>",
            "gid://shopify/ProductVariant/<ID of second child product variant>"
          ]
        },
        "component_quantities": {
          "value": [
            <quantity of first product variant in bundle>,
            <quantity of second product variant in bundle>
          ]
        }
      }
    ]