--- title: Verify theme support description: >- Learn how to determine whether an online store's published theme supports app block and which version of your app they can install. source_url: html: 'https://shopify.dev/docs/apps/build/online-store/verify-support' md: 'https://shopify.dev/docs/apps/build/online-store/verify-support.md' --- # Verify theme support Before you start integrating your app, determine the method required for integrating an app with an online store by verifying whether its published theme supports app blocks. **Tip:** If a theme doesn't currently support app blocks, and you maintain the theme or a store where the theme is used, then you can also consider [migrating the theme to support app blocks](https://shopify.dev/docs/storefronts/themes/os20#migrating-to-online-store-2-0). *** ## Verification criteria To verify whether a theme supports app blocks, you need to determine the following: * Whether the template where your app is injected supports [JSON](https://shopify.dev/docs/storefronts/themes/architecture/templates/json-templates). * The main section in the template. * Whether the section where your app is injected has a block of type [`@app`](https://shopify.dev/docs/storefronts/themes/architecture/blocks/app-blocks) in its schema. For an example, refer to Shopify's sample [product reviews app](https://github.com/Shopify/product-reviews-sample-app). *** ## Requirements You've requested the `read_themes` [GraphQL Admin API access scope](https://shopify.dev/docs/api/usage/access-scopes#authenticated-access-scopes). *** ## Verify support for app blocks You can use the following code to verify that a theme supports app blocks. The code uses [Shopify's Node library](https://shopify.dev/docs/api#api-libraries), which provides support for JavaScript apps to access the [GraphQL Admin API](https://shopify.dev/docs/api/admin-graphql). ```js import {shopifyApi} from '@shopify/shopify-api'; // Create library object const shopify = shopifyApi({ // The next four values are typically read from environment variables for added security apiKey: 'APIKeyFromPartnerDashboard', apiSecretKey: 'APISecretFromPartnerDashboard', scopes: ['read_products'], hostName: 'cloudflare-tunnel-address', ... }); // Specify the name of the template that the app will integrate with const APP_BLOCK_TEMPLATES = ["product", "collection", "index"]; const getMainThemeId = ` query getMainThemeId { themes(first: 1, roles: [MAIN]) { nodes { id } } }`; let response = await client.request(getMainThemeId); const themeId = response.data.themes.nodes[0].id; // Retrieve the JSON templates that we want to integrate with const getFilesQuery = ` query getFiles($filenames: [String!]!, $themeId: ID!) { theme(id: $themeId) { files(filenames: $filenames) { nodes { filename body { ... on OnlineStoreThemeFileBodyText { content } ... on OnlineStoreThemeFileBodyBase64 { contentBase64 } } } } } } `; response = await client.request(getFilesQuery, { variables: { themeId: themeId, filenames: APP_BLOCK_TEMPLATES.map((f) => `templates/${f}.json`), }, }); const jsonTemplateFiles = response.data.theme.files.nodes; if ( jsonTemplateFiles.length > 0 && jsonTemplateFiles.length === APP_BLOCK_TEMPLATES.length ) { console.log("All desired templates support sections everywhere!"); } else if (jsonTemplateFiles.length) { console.log( "Only some of the desired templates support sections everywhere.", ); } const jsonTemplateData = jsonTemplateFiles.map((file) => { return { filename: file.filename, body: jsonc_parse(file.body.content) }; }); // Retrieve the body of JSON templates and find what section is set as `main` const templateMainSections = jsonTemplateData .map((file) => { const main = Object.entries(file.body.sections).find( ([id, section]) => id === "main" || section.type.startsWith("main-"), ); if (main) { return "sections/" + main[1].type + ".liquid"; } }) .filter((section) => section); const sectionFiles = await client.request(getFilesQuery, { variables: { themeId: themeId, filenames: templateMainSections }, }); const sectionsWithAppBlock = sectionFiles.data.theme.files.nodes .map((file) => { let acceptsAppBlock = false; const match = file.body.content.match( /\{\%\s+schema\s+\%\}([\s\S]*?)\{\%\s+endschema\s+\%\}/m, ); const schema = jsonc_parse(match[1]); if (schema && schema.blocks) { acceptsAppBlock = schema.blocks.some((b) => b.type === "@app"); } return acceptsAppBlock ? file : null; }) .filter((section) => section); if ( jsonTemplateData.length > 0 && jsonTemplateData.length === sectionsWithAppBlock.length ) { console.log( "All desired templates have main sections that support app blocks!", ); } else if (sectionsWithAppBlock.length) { console.log("Only some of the desired templates support app blocks."); } else { console.log("None of the desired templates support app blocks"); } ``` *** ## Specify the method for integrating the app | App block support | Integration method | | - | - | | Yes | Skip requests made to the `ScriptTag` object. | | No | Make requests to the `ScriptTag` object, or provide instructions to add code using a [custom Liquid](https://help.shopify.com/manual/online-store/themes/theme-structure/extend#add-custom-html-or-liquid) section or block, or the [custom CSS](https://help.shopify.com/manual/online-store/themes/theme-structure/extend/add-css) setting. | *** ## Provide onboarding instructions You need to provide merchants with post-installation instructions about onboarding your app. To learn more about writing effective help documentation, refer to [Help documentation](https://polaris.shopify.com/content/help-documentation) in Shopify Polaris and to the theme app extension [onboarding instruction guidelines](https://shopify.dev/docs/apps/build/online-store/theme-app-extensions/ux#merchant-onboarding). | App block support | Onboarding | | - | - | | Yes | Provide merchants with instructions about using the app block.For example, document instructions for adding the app block to the theme. | | No | Provide merchants with instructions about any configurations required to integrate the app.For example, document instructions for copying and pasting a code snippet to a page. | ***