---
gid: 60bd9a24-c5ec-4aa0-97af-b58496bd6fae
title: Build a product discount function
description: Use Shopify Functions to add a product discount function to an existing app.
---
import RequirementPartial from 'app/views/partials/apps/discounts/requirements_partial.mdx';
import CreateFunction from 'app/views/partials/apps/discounts/create-function.mdx';
import DeployAndReinstallApp from 'app/views/partials/apps/discounts/deploy-and-reinstall-app.mdx';
import RegenerateTypes from 'app/views/partials/apps/discounts/regenerate-types.mdx';
import ReviewFunctionExecution from 'app/views/partials/apps/app-extensions/review-function-execution.md';

<Repo extension="rust" href="https://github.com/Shopify/tutorial-discount-functions-with-remix" />
<Repo extension="javascript" href="https://github.com/Shopify/tutorial-discount-functions-with-remix" />

<Picker name="extension">
  <PickerOption name="javascript" />
  <PickerOption name="rust" />
</Picker>

<Overview>

  You can create a new type of discount that's applied to a particular product or product variant in the cart. In this tutorial, you'll use [Shopify Functions](/docs/apps/build/functions) to create a new discount type called "Volume discount" that offers a percentage off when customers purchase more than the minimum quantity of a product.

  ## What you'll learn

  In this tutorial, you'll learn how to do the following tasks:

  - Generate starter code for Shopify Functions.
  - Use GraphQL to define the input of your Function.
  - Deploy Functions to the Shopify platform.
  - Review logs for your Function.

</Overview>

<Requirements>
  <RequirementPartial />
</Requirements>

<StepSection>
  <Step>
    <CreateFunction functionName="Product Discount">
      ```bash
      shopify app generate extension --template product_discounts --name product-discount
      ```
    </CreateFunction>
  </Step>
  <Step>
    ## Update the configuration

    <Substep>
      ### Replace the content of the `run.graphql` file
      <CodeRef extension="rust" href="https://github.com/Shopify/tutorial-discount-functions-with-remix/blob/main/extensions/product-discount-start/src/run.graphql" tag="product-discount.configuration" />
      <CodeRef extension="javascript" href="https://github.com/Shopify/tutorial-discount-functions-with-remix/blob/main/extensions/product-discount-start-js/src/run.graphql" tag="product-discount.configuration" />
        Replace the contents of `run.graphql`. This file defines the input for the Function target.
    </Substep>
    <If extension="javascript">
      <Substep>
        Navigate to your extension's directory:
            <Codeblock terminal>
            ```bash
            cd extensions/product-discount
            ```
            </Codeblock>
      </Substep>
      <Substep>
          <RegenerateTypes />
      </Substep>
    </If>
  </Step>
  <Step>
    ## Update the Function logic
    <Substep>
      <CodeRef extension="rust" href="https://github.com/Shopify/tutorial-discount-functions-with-remix/blob/main/extensions/product-discount-start/src/run.rs" tag="product-discount-start" />
      <CodeRef extension="javascript" href="https://github.com/Shopify/tutorial-discount-functions-with-remix/blob/main/extensions/product-discount-start-js/src/run.js" tag="product-discount-start" />

      ### Replace the content in <If extension="javascript">`run.js`</If> <If extension="rust"> `run.rs` </If>

      This Function logic applies a 10% discount to any cart lines with a quantity of two or more.
    </Substep>

    <Substep>
      <CodeRef extension="javascript" href="https://github.com/Shopify/tutorial-discount-functions-with-remix/blob/main/extensions/product-discount-start-js/src/run.js" tag="product-discount-start.cart-targets" />
      <CodeRef extension="rust" href="https://github.com/Shopify/tutorial-discount-functions-with-remix/blob/main/extensions/product-discount-start/src/run.rs" tag="product-discount-start.cart-targets" />

      Iterate through all cart lines to create discount targets, including only those with a quantity of two or more. Use the cart line ID to create each discount target.
    </Substep>

    <Substep>
      <CodeRef extension="javascript" href="https://github.com/Shopify/tutorial-discount-functions-with-remix/blob/main/extensions/product-discount-start-js/src/run.js" tag="product-discount-start.discount" />
      <CodeRef extension="rust" href="https://github.com/Shopify/tutorial-discount-functions-with-remix/blob/main/extensions/product-discount-start/src/run.rs" tag="product-discount-start.discount" />

      Apply the discount to the collected targets by creating a discount object and define a percentage-based discount.

    </Substep>
    <br/>
    <Notice type="info">
      <If extension="rust">
        The [shopify_function crate](https://crates.io/crates/shopify_function) serializes your [`FunctionRunResult`](/docs/api/functions/reference/product-discounts/graphql#functionrunresult) and writes it to STDOUT.
      </If>
      <If extension="javascript">
        The [@shopify/shopify_function package](https://www.npmjs.com/package/@shopify/shopify_function) applies `JSON.stringify()` to your [`FunctionRunResult`](/docs/api/functions/reference/product-discounts/graphql#functionrunresult).
      </If>
    </Notice>
  </Step>
  <Step>

    ##  Preview the Function on a development store

    To test your Function, you need to make it available to your development store.
    <If extension="rust">
    1. Ensure you have configured `build.watch` in your [function extension configuration](/docs/api/functions/configuration#properties).
    </If>

    1. Use Shopify CLI's [`dev` command](/docs/api/shopify-cli/app/app-dev) to preview the app:

          <Codeblock terminal>
          ```bash
            shopify app dev
          ```
          </Codeblock>

          You can keep the preview running as you work on your Function. When you make changes to a watched file, Shopify CLI rebuilds your Function and updates the Function extension's drafts, so that you can immediately test your changes.

    1. Follow the CLI prompts to preview your app, and install it on your development store.
  </Step>
  <Step>
    ## Update your app's access scopes

    You must request the `write_discounts` [access scope](/docs/api/usage/access-scopes) to give your app the permissions that it needs to create and update discounts.

    <Substep>
      <CodeRef extension="rust" href="https://github.com/Shopify/tutorial-discount-functions-with-remix/blob/main/shopify.app.toml" tag="discount-allocator.access_scopes" />
      <CodeRef extension="javascript" href="https://github.com/Shopify/tutorial-discount-functions-with-remix/blob/main/shopify.app.toml" tag="discount-allocator.access_scopes" />

      In `shopify.app.toml`, located in the root of your app, add the `write_discounts` scope to the `access_scopes` array.
    </Substep>

  </Step>
  <Step>
    <DeployAndReinstallApp />
  </Step>
  <Step>
    ## Install the GraphiQL app

    To activate your Function, you must create a product discount on the store where you installed your app. You can do this using the [`discountAutomaticAppCreate`](/docs/api/admin-graphql/latest/mutations/discountAutomaticAppCreate) or [`discountCodeAppCreate`](/docs/api/admin-graphql/latest/mutations/discountCodeAppCreate) GraphQL mutations.
      1. Install the [Shopify GraphiQL app](https://shopify-graphiql-app.shopifycloud.com/) on your store.
      1. Make sure to select the `write_discounts` access scopes for the Admin API.
      1. In the GraphiQL app, in the **API Version** field, select the **2023-07** version or higher.
        <Notice type="note">
          If you've already installed GraphiQL, then uninstall and reinstall it so that you can select the `write_discounts` access scope.
        </Notice>
  </Step>

  <Step>
    ## Create the product discount with GraphiQL
    In this step, you'll use the Shopify GraphiQL app to create a product discount function on your store. This involves querying your Function's ID and using it to create the discount with the appropriate GraphQL mutation.

    ---

    In subsequent tutorials, you'll use [metafields](/docs/api/checkout-ui-extensions/latest/apis/metafields) on this product discount function to configure your Function, and create an interface so that users can configure the Function themselves.

    <Substep>
      <CodeRef extension="rust" href="https://github.com/Shopify/tutorial-discount-functions-with-remix/blob/main/graphql_examples/find-function-query.graphql" tag="find-function-query" />
      <CodeRef extension="javascript" href="https://github.com/Shopify/tutorial-discount-functions-with-remix/blob/main/graphql_examples/find-function-query.graphql" tag="find-function-query" />
      ### Query the shopify Function

      Use the [`shopifyFunctions`](/docs/api/admin-graphql/latest/queries/shopifyFunctions) query to get the ID of your Function.

      ---
      The result contains a node with your Function's ID.
      <Codeblock>
      ```json
      {
        "app": {
          "title": "your-app-name-here"
        },
        "apiType": "product_discounts",
        "title": "product-discount",
        "id": "YOUR_FUNCTION_ID_HERE"
      }
      ```
      </Codeblock>
    </Substep>

    <Substep>
      <CodeRef extension="rust" href="https://github.com/Shopify/tutorial-discount-functions-with-remix/blob/main/graphql_examples/discountAutomaticAppCreate.graphql" tag="discount-automatic-app-create" />
      <CodeRef extension="javascript" href="https://github.com/Shopify/tutorial-discount-functions-with-remix/blob/main/graphql_examples/discountAutomaticAppCreate.graphql" tag="discount-automatic-app-create" />
      ### Create the product discount function
      Use the [`discountAutomaticAppCreate`](/docs/api/admin-graphql/latest/mutations/discountAutomaticAppCreate) mutation to create a product discount function.
    </Substep>


    <Substep>
      <CodeRef extension="rust" href="https://github.com/Shopify/tutorial-discount-functions-with-remix/blob/main/graphql_examples/discountAutomaticAppCreate.graphql" tag="discount-automatic-app-create.add-function-id" />
      <CodeRef extension="javascript" href="https://github.com/Shopify/tutorial-discount-functions-with-remix/blob/main/graphql_examples/discountAutomaticAppCreate.graphql" tag="discount-automatic-app-create.add-function-id" />

      Add the Shopify Function ID from the [previous step](/docs/apps/build/discounts/build-discount-function?extension=rust#query-the-shopify-function) as the value for the `functionId` input.
    </Substep>

    <br/>
    You should receive a GraphQL response that includes the ID of the created product discount. If the response includes any messages under `userErrors`, then review the errors, check that your mutation and `functionId` are correct, and try the request again.

    <Troubleshooting>
      If you receive a `Could not find Function` error, then confirm the following:
      - The Function ID is correct.
      - You've installed the app on your development store.
      - [Development store preview](#preview-the-function-on-a-development-store) is enabled in the Partner Dashboard.
      - Your app has the `write_discounts` access scope.
    </Troubleshooting>
  </Step>
  <Step>
    ## Test the product discount

    <Substep>
    ### Trigger the discount on your development store
    1. From your Shopify admin, go to **Discounts**.

        You should now see the **Volume discount** that you created.

        ![An image showing a list of all active discounts for the store.](/assets/apps/discounts/functions-discount-list.png)

    1. Deactivate or delete all other discounts to ensure that the **Volume discount** is the only active discount.
    1. Open your development store and build a cart with a single item in it.

        No discounts should be applied to the cart.
    1. Increase the item quantity to two.

            The 10% **Volume discount** should now be applied to the cart.
    </Substep>
    <Substep>
      <ReviewFunctionExecution />
    </Substep>
  </Step>
</StepSection>


<NextSteps>
  ## Tutorial complete!
  You've successfully created a product discount function using Shopify Functions. You can now use this Function to apply discounts targeting cart lines with a quantity of two or more.

  ### Next Steps
  <CardGrid>

    <LinkCard href="/docs/apps/build/discounts/build-ui-with-remix">
      #### Build a user interface for your discount Function

      Add configuration to your discounts experience using metafields and build a user interface for your Function.
    </LinkCard>
  </CardGrid>
</NextSteps>