graphQL: Detecting app blocks and app embed blocks ?

Solved

graphQL: Detecting app blocks and app embed blocks ?

den232
Shopify Partner
227 8 58

It appears that I can detect whether my app is embedded via the dying REST, but how to do it with graphQL? This is part of my app install automation …

Detecting app blocks and app embed blocks

Anchor link to section titled “Detecting app blocks and app embed blocks”

If you want to identify whether a merchant has added app blocks to their theme, or enabled app embed blocks, you can use the Asset REST Admin API resource to look for blocks that match your app type. …

Any suggestions?

Accepted Solution (1)

Deluxe-Foladun
Shopify Partner
57 9 12

This is an accepted solution.

Hi @den232,
Foladun here from the Deluxe App team. 👋

I solved this by querying the store's themes and checking the settings_data.json file for app-related blocks.
In my case, the block I needed was in the settings_data.json file, but you can adapt this approach to check any template or file relevant to your app.

Here’s an example:

 

 

const response = await admin.graphql(`
  query GetStoreThemes {
    themes(first: 10) {
      edges {
        node {
          files(filenames: ["config/settings_data.json"]) {  // Replace with the file you're targeting
            edges {
              node {
                body {
                  ... on OnlineStoreThemeFileBodyText {
                    content
                  }
                }
              }
            }
          }
        }
      }
    }
  }
`);

const responseData = JSON.parse(await response.text()).data;
const themes = responseData.themes.edges;

themes.forEach(theme => {
  const contentJson = JSON.parse(theme.node.files.edges[0].node.body.content);
  const fileBlocks = contentJson?.current?.blocks || {};
  
  const appBlockKey = Object.keys(fileBlocks).find(blockKey =>
    fileBlocks[blockKey].type.includes('<replace-with-your-app-namespace>/blocks/<replace-with-your-block-type>')
  );
  
  const appIsInstalled = appBlockKey && !fileBlocks[appBlockKey].disabled;

});

 

 


In this example, I check the settings_data.json file because that's where my app block was located.
However, you can replace "config/settings_data.json" with any file or template you're targeting and adjust the block type accordingly (e.g., '<replace-with-your-app-namespace>/blocks/<replace-with-your-block-type>''.

Let me know if this helps or if you need more information!

Best regards,

Foladun | Deluxe: Account & Loyalty

• Boost engagement and sales with Customer Account Deluxe: a Modern Customer Page with Loyalty, Wishlist, and Social Login (Free plan available)


• Drive more revenue, increases user retention and repeat purchases, with simple one-click installation.

View solution in original post

Replies 7 (7)

Deluxe-Foladun
Shopify Partner
57 9 12

This is an accepted solution.

Hi @den232,
Foladun here from the Deluxe App team. 👋

I solved this by querying the store's themes and checking the settings_data.json file for app-related blocks.
In my case, the block I needed was in the settings_data.json file, but you can adapt this approach to check any template or file relevant to your app.

Here’s an example:

 

 

const response = await admin.graphql(`
  query GetStoreThemes {
    themes(first: 10) {
      edges {
        node {
          files(filenames: ["config/settings_data.json"]) {  // Replace with the file you're targeting
            edges {
              node {
                body {
                  ... on OnlineStoreThemeFileBodyText {
                    content
                  }
                }
              }
            }
          }
        }
      }
    }
  }
`);

const responseData = JSON.parse(await response.text()).data;
const themes = responseData.themes.edges;

themes.forEach(theme => {
  const contentJson = JSON.parse(theme.node.files.edges[0].node.body.content);
  const fileBlocks = contentJson?.current?.blocks || {};
  
  const appBlockKey = Object.keys(fileBlocks).find(blockKey =>
    fileBlocks[blockKey].type.includes('<replace-with-your-app-namespace>/blocks/<replace-with-your-block-type>')
  );
  
  const appIsInstalled = appBlockKey && !fileBlocks[appBlockKey].disabled;

});

 

 


In this example, I check the settings_data.json file because that's where my app block was located.
However, you can replace "config/settings_data.json" with any file or template you're targeting and adjust the block type accordingly (e.g., '<replace-with-your-app-namespace>/blocks/<replace-with-your-block-type>''.

Let me know if this helps or if you need more information!

Best regards,

Foladun | Deluxe: Account & Loyalty

• Boost engagement and sales with Customer Account Deluxe: a Modern Customer Page with Loyalty, Wishlist, and Social Login (Free plan available)


• Drive more revenue, increases user retention and repeat purchases, with simple one-click installation.

den232
Shopify Partner
227 8 58

That is so brilliant!  Works like a charm!   I'm so happy to actually say 'bye to REST!  Thanks so much!     

 

(I think 4 exclamations is about right)

 

Cheers jb

Deluxe-Foladun
Shopify Partner
57 9 12

I'm very glad it worked for you too!
Happy coding!! 🙂

Cheers

• Boost engagement and sales with Customer Account Deluxe: a Modern Customer Page with Loyalty, Wishlist, and Social Login (Free plan available)


• Drive more revenue, increases user retention and repeat purchases, with simple one-click installation.

VegetaLBD
Shopify Partner
2 0 0

Hello, I try your way, but I face an error: 
"errors": [
{
"message": "Access denied",
"locations": [
{
"line": 7,
"column": 9
}
],
"path": [
"themes",
"edges",
4,
"node",
"files"
]
}
]
How to fix it?

den232
Shopify Partner
227 8 58

Hi Veg, I think that means that the shop has not granted your app all the access privileges it needs.   Look for some that refer to themes.  jb

Deluxe-Foladun
Shopify Partner
57 9 12

That's correct, because if you're retrieving config/settings_data.json to get app blocks you'll probably get app embed blocks, as app blocks may not be stored in that file. 
You can retrieve other specific template files to get app blocks.

Hope this helps!

• Boost engagement and sales with Customer Account Deluxe: a Modern Customer Page with Loyalty, Wishlist, and Social Login (Free plan available)


• Drive more revenue, increases user retention and repeat purchases, with simple one-click installation.

den232
Shopify Partner
227 8 58

Yeah, you have to strip that crap (which sometimes appears) between the /* ... */ 

 

My code looks like this:

 

	// Remove everything between /* and */, then parse for json
	let themeContent = {};
	let mainThemeCleaned = '{}';
	let mainThemeRaw = '{}';
	try {
		mainThemeRaw = mainTheme?.files?.nodes?.[0]?.body?.content || '{}';
		const ix1 = mainThemeRaw.indexOf('/*');
		const ix2 = mainThemeRaw.indexOf('*/', ix1+2);
		if (ix1 >= 0 && ix2 >= 0) {
			mainThemeCleaned
				= mainThemeRaw.substring(0, ix1 - 1)
				+ mainThemeRaw.substring(ix2 + 2);
			console.log('cleaned', ix2 - ix1 - 2,
				'comment characters from main theme text')
		}
		themeContent = JSON.parse(mainThemeCleaned);
	} catch (err) {
		console.error('unable to parse mainTheme for block content', err);
	}

Good luck!  jb