--- title: Use extensions to surface app data description: Use extensions to surface app data source_url: html: 'https://shopify.dev/docs/apps/build/sidekick/build-app-data' md: 'https://shopify.dev/docs/apps/build/sidekick/build-app-data.md' --- ExpandOn this page * [Requirements](https://shopify.dev/docs/apps/build/sidekick/build-app-data.md#requirements) * [Allow Sidekick to use your app's data](https://shopify.dev/docs/apps/build/sidekick/build-app-data.md#allow-sidekick-to-use-your-apps-data) * [Putting it all together](https://shopify.dev/docs/apps/build/sidekick/build-app-data.md#putting-it-all-together) # Use extensions to surface app data Developer preview The features and functionality in this guide are in developer preview and subject to change. We welcome feedback and suggestions on the [Shopify Developer Community](https://community.shopify.dev/). Use an app extension to expose data in your app to Sidekick. By providing your app's data in an app extension, Sidekick can search your app's data to get tailored results. Merchants can get value from your app just by working with Sidekick, while also staying in their flow. ### Use case example in this guide This guide shows you how to allow Sidekick to search your app's data. You can use this example to build your own app extension for search, and other tasks. In this example, a merchant can ask Sidekick to find the best performing subject lines in their email campaigns. Sidekick searches using the app extension in the email app, then returns the best options. Clicking on an option invokes the email app, navigated right to the correct result. ![Sidekick email search interface](https://shopify.dev/assets/assets/admin/sidekick/email-performance-flow-C00FiYFF.png) *** ## Requirements * [Create an app](https://shopify.dev/docs/apps/build/scaffold-app). * For app home, use the latest version of [App Bridge](https://shopify.dev/docs/api/app-home). *** ## Allow Sidekick to use your app's data In this example, a merchant can ask Sidekick to find the best performing subject lines in their email campaigns. Sidekick searches using the app extension in the email app, then returns the best options. Clicking on an option invokes the email app, navigated right to the correct result. This app extension is headless, can be run at any point from anywhere, and can be called programmatically for Shopify search in the admin. ### Create an app extension Use `shopify-cli` to create an app extension. ## Terminal ```terminal shopify app generate extension --template app-tools --name tools ``` This will create a UI extension in the `extensions` folder. ## App tools folder structure ```toml extensions/tools ├── README.md ├── package.json ├── shopify.extension.toml // The config file for the extension ├── tsconfig.json ├── shopify.d.ts // Provides types for components and APIs available to the extension └── src └── index.js // The code that powers your app extension tools.json // The schema for your app extension (created in the next step) ``` ### Configure your app extension Customize your app's extension in `shopify.extension.toml` to include a `description`. Optionally, you can link to instructions for how Sidekick should use your app extension. ## extensions/tools/shopify.extension.toml ```toml [[extensions]] name = "Email Tools" description = "Tools for working with email, searching email campaigns, and getting email campaign stats" handle = "tools" type = "ui_extension" [[extensions.targeting]] module = "./src/index.js" target = "admin.app.tools.data" tools = "./tools.json" instructions = "./instructions.md" ``` Note `admin.app.tools.data` is a special target that is not tied to a Shopify resource and executes headlessly. The `description` field in `shopify.extension.toml` is optional, but is highly recommended for providing context to Sidekick about your app extension. Sidekick will use this field to determine when your extension might be useful to answer a merchant's question. ### Write your Java​Script module When your app's extension is invoked, your JavaScript will be called automatically in the Shopify sandbox. The sandbox provides access to [Direct API](https://shopify.dev/docs/api/admin-extensions/latest/network-features#direct-api-access) for making GraphQL queries, and [App Authentication](https://shopify.dev/docs/api/admin-extensions/latest/network-features#app-authentication) for fetching data from your app's backend. Your app extension must only be used for retrieving data from your app. If you need to perform actions in your app, use an [app extension](https://shopify.dev/docs/apps/build/sidekick/build-app-actions) and see [Resource Links](https://shopify.dev/docs/apps/build/sidekick/build-app-data#data-output-schema-best-practices) for more information. ## extensions/tools/src/index.js ```js export default () => { shopify.tools.register('get_campaigns', async ({name, date}) => { const response = await fetch('/api/campaigns', { method: 'POST', body: JSON.stringify({name, date}) }); return response.json(); }); shopify.tools.register('campaign_stats', async ({campaign_id}) => { const response = await fetch(`/api/campaigns/${campaign_id}/stats`); return response.json(); }); } ``` Note Your app extension should aim to return data to Sidekick as quickly as possible to keep the conversation feeling responsive. In practice, responses within a few hundred milliseconds are a good target. We'll share more specific performance guidance as we gather data from real usage. ### Write your tools schema Declare your schema in the `JSON` file referenced in `shopify.extension.toml`. ## ./tools.json ```json [ { "$schema": "https://extensions.shopifycdn.com/shopifycloud/schemas/v1/tool.json", "name": "get_campaigns", "description": "Search email marketing campaigns", "inputSchema": { "type": "object", "properties": { "name": { "type": "string", "description": "Perform a full text search" }, "after": { "type": "string", "description": "Cursor for pagination" }, "before": { "type": "string", "description": "Cursor for pagination" }, "first": { "type": "integer", "description": "Number of results to return" }, "last": { "type": "integer", "description": "Number of results from the end" }, "creationPeriod": { "type": "object", "properties": { "from": { "type": "string", "format": "date-time" }, "to": { "type": "string", "format": "date-time" } } }, "editedAtPeriod": { "type": "object", "properties": { "from": { "type": "string", "format": "date-time" }, "to": { "type": "string", "format": "date-time" } } }, "effectiveStatusDatePeriod": { "type": "object", "properties": { "from": { "type": "string", "format": "date-time" }, "to": { "type": "string", "format": "date-time" } } }, "marketingActivityStatuses": { "type": "array", "items": { "type": "string", "enum": [ "ACTIVE", "CANCELLED", "DELETED", "DRAFT", "FAILED", "INACTIVE", "PAUSED", "PENDING", "SCHEDULED" ] } }, "sortKey": { "type": "string", "enum": [ "CREATED_AT", "EDITED_AT", "EFFECTIVE_STATUS_DATE", "STATUS_UPDATED_AT", "SUBJECT", "UPDATED_AT" ] }, "sortOrder": { "type": "string", "enum": [ "ASC", "DESC" ] }, "contentType": { "type": "string", "enum": [ "CUSTOM_CODE_BODY", "THEME_INSTANCE" ] } } } }, { "$schema": "https://extensions.shopifycdn.com/shopifycloud/schemas/v1/tool.json", "name": "campaign_stats", "description": "Get statistics for a specific email marketing campaign", "inputSchema": { "type": "object", "properties": { "campaign_id": { "type": "string", "description": "The unique identifier of the campaign" } }, "required": ["campaign_id"] } } ] ``` ### Write instructions for using the app extension Define instructions fo how Sidekick should use your app extension in a `instructions.md` file. Note `instructions.md` is optional, but is highly recommended for providing context and guidance to Sidekick about your app extension. ## ./instructions.md ```md ## When to Use Email Tools Use these tools when the merchant asks about: - Email campaigns and newsletters - Subscriber lists and segments - Email automations and flows - Email marketing metrics ## Important Guidelines - Always confirm campaign details before sending - When creating segments, verify the conditions are correct - For campaign metrics, specify the date range if not provided - Email tools uses "flows" for automated email sequences (not "automations") ## Common Workflows ### Sending a Campaign 1. First verify the campaign exists using get_campaign 2. Confirm the target segment with the merchant 3. Use get_campaign_stats with the campaign ID ### Creating a Segment 1. Ask the merchant for the segmentation criteria 2. Translate their request into conditions 3. Create the segment and confirm the name ``` *** ## Putting it all together After following this tutorial, your `extensions` folder structure should look like this: ## Folder structure ```toml extensions/tools ├── instructions.md // The instructions for using the app extension ├── README.md // ├── package.json ├── tools.json // The schema for your tools ├── tsconfig.json ├── shopify.d.ts // Provides types for APIs available to the extension ├── shopify.extension.toml // The config file for the extension └── src └── index.js // The code that powers your app extension ``` ### Data output schema best practices Sidekick is optimized for results that are returned in Model Context Protocol's [Resource Links](https://modelcontextprotocol.io/specification/2025-06-18/server/tools#resource-links) format. Using the Resource Links format ensures Sidekick will know how to invoke your app's actions on the data returned by your extension. Use the `uri` field to link directly to a specific resource in your app. ## Example search campaign tool results ```js { results: [ { type: 'resource_link', uri: 'gid:application/email/123', name: 'Sale starts soon!', mimeType: 'application/email' } ] } ``` *** * [Requirements](https://shopify.dev/docs/apps/build/sidekick/build-app-data.md#requirements) * [Allow Sidekick to use your app's data](https://shopify.dev/docs/apps/build/sidekick/build-app-data.md#allow-sidekick-to-use-your-apps-data) * [Putting it all together](https://shopify.dev/docs/apps/build/sidekick/build-app-data.md#putting-it-all-together)