---

gid: a31f1697-7808-4d38-927c-f8c545bec25d
title: Build an admin action
description: Learn how to create admin action extensions on resource and index pages in the Shopify admin.
---

<Repo extension="react" href="https://github.com/Shopify/example-admin--action-and-block--react" />

<Picker name="extension">
  <PickerOption name="react" />
</Picker>

<Overview>
  This guide is the first part in a five-part tutorial series on how to build a feature using admin action and block extensions. The guide demonstrates how to build a basic action extension that enables users to log issues on products that can be tracked and resolved. The guide also demonstrates how to create admin action extensions that can be launched from an admin block extension with extra context about what resource or data the action should pre-populate for editing.

  ![The issue tracker action over a modal. The action has input fields for a title and description.](/assets/admin/admin-actions-and-block/build-an-admin-action/opened-action.png)

  ## What you'll learn

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

  - Create an admin action extension that displays on the product details page
  - Fetch information to populate the extensions's initial state
  - Create a UI for the extension that enables it to gather more input from merchants
  - Update the data using GraphQL based on merchant input
  - Run the extension locally and test it on a development store
</Overview>

<Requirements>
  <Requirement href="https://www.shopify.com/partners" label="Create a Partner account" />

  <Requirement href="/docs/apps/tools/development-stores#create-a-development-store-to-test-your-app" label="Create a development store" />

  <Requirement href="/docs/apps/build/scaffold-app" label="Scaffold an app">
    Scaffold an app with the `write_products` access scope that uses [Shopify CLI 3.71 or higher](/docs/api/shopify-cli#upgrade).

    - If you created a Remix app, then the `write_products` access scope is automatically granted to your app.
    - If you created an extension-only app, then you need to explicitly grant the `write_products` access scope to your [custom app](/docs/apps/auth/access-token-types/admin-app-access-tokens#changing-api-scopes).
  </Requirement>
</Requirements>

<StepSection>
  <Step>
    ## Create a new extension

    Use Shopify CLI to [generate starter code](/docs/api/shopify-cli/app/app-generate-extension) for your action extension.

    1.  Navigate to your app directory:
        <Codeblock terminal>
          ```bash
          cd <directory>
          ```
        </Codeblock>

    2.  Run the following command to create a new admin action extension:

        <Codeblock terminal>
          ```bash
          shopify app generate extension --template admin_action --name issue-tracker-action --flavor react
          ```
        </Codeblock>

        The command creates a new extension template in your app's `extensions` directory with the following structure:

        <Codeblock title="Admin action structure">
          ```text
            extensions/issue-tracker-action
            ├── README.md
            ├── locales
            │   ├── en.default.json // The default locale for the extension
            │   └── fr.json // The French language translations for the extension
            ├── package.json
            ├── shopify.extension.toml // The config file for the extension
            └── src
                └── AdminAction.jsx // The code that defines the action's UI and behavior
          ```
        </Codeblock>
  </Step>

  <Step>
    ## Write the extension's UI

    Complete the following steps to write the extension's UI:

    <Substep>
      <CodeRef extension="react" href="https://github.com/Shopify/example-admin--action-and-block--react/blob/main/extensions/issue-tracker-action/shopify.extension.toml" tag="action-extension.configuration"/>

      ### Review the configuration

      The extension's `.toml` file stores the extension's static configuration. To have the issue tracker display product detail pages, validate that the `target` is set to `admin.product-details.action.render`.

      <Resources>
        [admin.product-details.action.render](/docs/api/admin-extensions/latest/api/extension-targets#extensiontargets-propertydetail-adminproductdetailsactionrender)
      </Resources>
    </Substep>

    <Substep>
      <CodeRef extension="react" href="https://github.com/Shopify/example-admin--action-and-block--react/blob/main/extensions/issue-tracker-action/locales/en.default.json" />

      ### Update title

      To update the display name when merchants select the action from the menu, in locale files edit the `name` value. The action extension uses the [i18n API](/docs/api/admin-extensions/api/action-extension-api#actionextensionapi-propertydetail-i18n) to translate strings so that your app is more accessible to a wider audience. This API gives you access to the strings stored in the locale files, and automatically chooses the correct string for the current user's locale.
    </Substep>

    <Substep>
      <CodeRef extension="react" href="https://github.com/Shopify/example-admin--action-and-block--react/blob/main/extensions/issue-tracker-action/locales/fr.json" />

      ### Translate title

      Optionally translate your title to French.
    </Substep>

    <Substep>
      <CodeRef extension="react" href="https://github.com/Shopify/example-admin--action-and-block--react/blob/main/extensions/issue-tracker-action/src/ActionExtension.jsx" tag="build-admin-action.create-ui-one"/>

      ### Use UI components

      Admin UI extensions are rendered using [Remote UI](https://github.com/Shopify/remote-dom/tree/remote-ui), which is a fast and secure remote-rendering framework. Because Shopify renders the UI remotely, components used in the extensions must comply with a contract in the Shopify host. We provide these components through the admin UI extensions library.

      <Resources>
        [Admin UI extensions components](/docs/api/admin-extensions/components)
      </Resources>
    </Substep>

    <Substep>
      <CodeRef extension="react" href="https://github.com/Shopify/example-admin--action-and-block--react/blob/main/extensions/issue-tracker-action/src/ActionExtension.jsx" tag="build-admin-action.create-ui-two"/>

      ### Note the export

      You can view the source of your extension in the `src/ActionExtension.jsx` file. This file defines a functional React component exported to run at the extension's target. You can create the extension's body by importing and using components from the `@shopify/ui-extensions-react/admin` package.

      <Notice type="warning" title="Caution">
        The extension point in the component export must match the extension point defined in your `.toml` file, or the extension won't render.
      </Notice>

    </Substep>

    <Substep>
      <CodeRef extension="react" href="https://github.com/Shopify/example-admin--action-and-block--react/blob/main/extensions/issue-tracker-action/src/ActionExtension.jsx" tag="build-admin-action.create-ui-three"/>

      ### Render a UI

      To build your action's UX, return some components from `src/ActionExtension.jsx`.

    </Substep>

    <br />

    <Notice type="note" title="Tip">
      At this point, you can use the developer console to [run your app's server and preview your extension](#step-4-test-the-extension). After you preview the extension, changes to your extension's code automatically reload the extension that you're previewing. This enables you to preview your extension and see it update live as you make changes to the code.
    </Notice>
  </Step>

  <Step>
    ## Write the extension logic and connect to the GraphQL Admin API

    After defining the extension's UI, use standard React tooling to write the logic that controls the extension.

    When you're writing extensions, you don't need proxy calls to the [GraphQL Admin API](/docs/api/admin-graphql) through your app's backend. Instead, your extension can use [direct API access](/docs/api/admin-extensions#directapiaccess) to create requests directly using `fetch`. This helps extensions be more performant and responsive for merchants.

    In this step, you'll create a utility file to contain GraphQL queries that the extension uses to read and write data to the metafield API.

    Your app can also get data from the extension APIs, which includes data on the current resource from the `data` API.

    <Substep>
      <CodeRef extension="react" href="https://github.com/Shopify/example-admin--action-and-block--react/blob/main/extensions/issue-tracker-action/src/utils.js" />

      Add new file at `./src/utils.js`. This file contains the GraphQL queries that the extension uses to read and write data to the GraphQL Admin API.

      <Resources>
        [metafieldDefinitionCreate](/docs/api/admin-graphql/latest/mutations/metafieldDefinitionCreate)
        [metafieldsSet](/docs/api/admin-graphql/latest/mutations/metafieldsSet)
      </Resources>
    </Substep>

    <Substep>
      <CodeRef extension="react" href="https://github.com/Shopify/example-admin--action-and-block--react/blob/main/extensions/issue-tracker-action/src/ActionExtension.jsx" tag="build-admin-action.connect-api-one"/>

      Import the `getIssues` utility method and use it to update the extension state.
    </Substep>

    <Substep>
      <CodeRef extension="react" href="https://github.com/Shopify/example-admin--action-and-block--react/blob/main/extensions/issue-tracker-action/src/ActionExtension.jsx" tag="build-admin-action.connect-api-two"/>

      Call the `updateIssues` utility method when the form is submitted.
    </Substep>
  </Step>

  <Step>
    ## Test the extension

    After you've built the extension, test it with the following steps:

    1.  Navigate to your app directory:

        <Codeblock terminal>
          ```bash
          cd <directory>
          ```
        </Codeblock>

    2.  To build and preview your app, either start or restart your server with the following command:

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

    3.  Press `p` to open the developer console.

    4.  In the developer console page, click on the preview link for the issue tracker action extension.

    5.  The product details page opens. If you don't have a product in your store, then you need to create one.

    6.  To launch your extension, in the top right of the page click the **More actions** dropdown list and select your extension.

    7.  Fill out the modal and click **Create**.

    8.  Validate that the metafield is created and populated with your issue text, by navigating to the metafields card at the bottom of the page, and select **Show all**.

    Update your code to the control the form and write the data to the admin metafield API using the methods from `./src/utils.js`.
  </Step>
</StepSection>

<NextSteps>
  ### Next steps

  <CardGrid>
    <LinkCard href="/docs/apps/admin/admin-actions-and-blocks/build-an-admin-block">
      #### Block extension

      Complete the next guide in this tutorial series by building a block extension to list the issues created by the action extension.
    </LinkCard>

    <LinkCard href="/docs/api/admin-extensions/extension-targets">
      #### Extension targets

      Learn about the surfaces in the Shopify admin where you can create admin extensions.
    </LinkCard>

    <LinkCard href="/docs/api/admin-extensions/components">
      #### Components

      Learn about the full set of available components for writing admin UI extensions.
    </LinkCard>
  </CardGrid>
</NextSteps>