App reviews, troubleshooting, and recommendations
I have created an app, and with the admin's panel, we can add any section to the theme. However, I want to ensure that when the app is uninstalled, any section and template files that were added also get deleted at the time of uninstallation.
My app is built using a Node.js template, and it fetches data from a GraphQL API.
Here is my code for deleting the theme file:
app.post('/api/theme/fileDelete', async (req, res) => { try { // Initialize Shopify client const client = new shopify.api.clients.Graphql({ session: res.locals.shopify.session, }); const themeId = "gid://shopify/OnlineStoreTheme/146551537909"; // specify your theme ID const filesToDelete = ["templates/index3.liquid"]; // specify the files to delete // Set up GraphQL mutation to delete theme files let mutation = `mutation($themeId: ID!, $files: [String!]!) { themeFilesDelete(themeId: $themeId, files: $files) { deletedThemeFiles { filename } userErrors { field message } } }`; // Send the request const response = await client.request(mutation, { variables: { themeId, files: filesToDelete } }); // Log the result and send a response console.log("Files deleted:", response.data); res.status(200).send({message: "Theme files deleted"}); } catch (error) { console.error("Error deleting theme files on uninstall:", error); res.status(500).send({message: error}); } }); //or const themeFileDelete = async (req,res) => { try { // Initialize Shopify client const client = new shopify.api.clients.Graphql({ session: res.locals.shopify.session, }); const themeId = "gid://shopify/OnlineStoreTheme/146551537909"; // specify your theme ID const filesToDelete = ["templates/index3.liquid"]; // specify the files to delete // Set up GraphQL mutation to delete theme files let mutation = `mutation($themeId: ID!, $files: [String!]!) { themeFilesDelete(themeId: $themeId, files: $files) { deletedThemeFiles { filename } userErrors { field message } } }`; // Send the request const response = await client.request(mutation, { variables: { themeId, files: filesToDelete } }); // Log the result and send a response console.log("Files deleted:", response.data); res.status(200).send({message:"delete theme file"}) // Optionally, you can also send a confirmation response back to the shop (if needed) } catch (error) { console.error("Error deleting theme files on uninstall:", error); res.status(500).send({message:error}) } }; export default themeFileDelete;
I have also set up a webhook for when the app is uninstalled, and it is working fine. However, I want the theme file deletion API to run only when the uninstall webhook is triggered.
Note: I have created the uninstall webhook in the privacy.js file, and I need to figure out how to run the theme deletion function from index.js when the uninstall webhook is triggered.
Here's how my webhook setup looks:
import { DeliveryMethod } from "@shopify/shopify-api"; import themeFileDelete from './index.js' /** * @type {{[key: string]: import("@shopify/shopify-api").WebhookHandler}} */ export default { /** * Customers can request their data from a store owner. When this happens, * Shopify invokes this privacy webhook. * * https://shopify.dev/docs/apps/webhooks/configuration/mandatory-webhooks#customers-data_request */ CUSTOMERS_DATA_REQUEST: { deliveryMethod: DeliveryMethod.Http, callbackUrl: "/api/webhooks", callback: async (topic, shop, body, webhookId) => { const payload = JSON.parse(body); // console.log(payload,"payloadpayload") // Payload has the following shape: // { // "shop_id": 954889, // "shop_domain": "{shop}.myshopify.com", // "orders_requested": [ // 299938, // 280263, // 220458 // ], // "customer": { // "id": 191167, // "email": "john@example.com", // "phone": "555-625-1199" // }, // "data_request": { // "id": 9999 // } // } }, }, /** * Store owners can request that data is deleted on behalf of a customer. When * this happens, Shopify invokes this privacy webhook. * * https://shopify.dev/docs/apps/webhooks/configuration/mandatory-webhooks#customers-redact */ CUSTOMERS_REDACT: { deliveryMethod: DeliveryMethod.Http, callbackUrl: "/api/webhooks", callback: async (topic, shop, body, webhookId) => { const payload = JSON.parse(body); // console.log(payload,"payload2") // Payload has the following shape: // { // "shop_id": 954889, // "shop_domain": "{shop}.myshopify.com", // "customer": { // "id": 191167, // "email": "john@example.com", // "phone": "555-625-1199" // }, // "orders_to_redact": [ // 299938, // 280263, // 220458 // ] // } }, }, /** * 48 hours after a store owner uninstalls your app, Shopify invokes this * privacy webhook. * * https://shopify.dev/docs/apps/webhooks/configuration/mandatory-webhooks#shop-redact */ SHOP_REDACT: { deliveryMethod: DeliveryMethod.Http, callbackUrl: "/api/webhooks", callback: async (topic, shop, body, webhookId) => { const payload = JSON.parse(body); // console.log(payload,"payload3") // console.log(payload,"appuninstall detata") // Payload has the following shape: // { // "shop_id": 954889, // "shop_domain": "{shop}.myshopify.com" // } }, }, /** * Webhook for when the app is uninstalled */ APP_UNINSTALLED: { deliveryMethod: DeliveryMethod.Http, callbackUrl: "/api/webhooks", callback: async (topic, shop, body, webhookId) => { const payload = JSON.parse(body); console.log(payload,"--------------Payload") console.log(topic,"--------------topic") console.log(shop,"--------------shop") console.log(webhookId,"--------------webhookId") await themeFileDelete() } } };
To ensure that your theme file deletion function is triggered properly during the uninstall webhook, you need to structure your webhook to correctly call the deletion function with the required parameters. Here’s how you can optimize your implementation:
Pass the Necessary Context to themeFileDelete:
Ensure themeFileDelete is Invoked with the Correct Parameters:
Update Your Webhook Callback:
Modify your themeFileDelete function to accept the necessary parameters for processing.
const themeFileDelete = async (shop, session) => { try { const client = new shopify.api.clients.Graphql({ session }); const themeId = "gid://shopify/OnlineStoreTheme/146551537909"; // Specify your theme ID const filesToDelete = ["templates/index3.liquid"]; // Files to delete const mutation = `mutation($themeId: ID!, $files: [String!]!) { themeFilesDelete(themeId: $themeId, files: $files) { deletedThemeFiles { filename } userErrors { field message } } }`; const response = await client.request(mutation, { variables: { themeId, files: filesToDelete } }); console.log("Files deleted:", response.data); return { success: true, message: "Theme files deleted successfully" }; } catch (error) { console.error("Error deleting theme files:", error); return { success: false, error }; } }; export default themeFileDelete;
Ensure the uninstall webhook creates a session for the shop and then invokes the themeFileDelete function.
APP_UNINSTALLED: { deliveryMethod: DeliveryMethod.Http, callbackUrl: "/api/webhooks", callback: async (topic, shop, body, webhookId) => { try { // Parse the webhook payload const payload = JSON.parse(body); console.log("Uninstall Payload:", payload); // Fetch the session for the shop const session = await shopify.utils.loadOfflineSession(shop); if (!session) { console.error("No session found for shop:", shop); return; } // Call the theme deletion function const result = await themeFileDelete(shop, session); if (result.success) { console.log("Theme files deleted successfully during app uninstallation."); } else { console.error("Error deleting theme files:", result.error); } } catch (error) { console.error("Error processing uninstall webhook:", error); } }, },
Webhook Triggers on Uninstallation:
Session Retrieval:
Invoke themeFileDelete:
File Deletion:
This structure ensures the theme files are removed only when the uninstall webhook is triggered, keeping your app and theme clean.
I updated the code and tried it, but it is still not working.
Is it possible that my app is not working because it's local, or do we need to create a separate URL for the webhook?
Note: The code after console.log("Uninstall Payload:", payload); is not working?
It looks like you're trying to ensure that when your app is uninstalled, any sections and template files added by the app are also deleted. You have set up a GraphQL mutation to delete files, and you want to ensure that this deletion occurs when the uninstall webhook is triggered.
From your code, you're importing the themeFileDelete function in the webhook setup, but to ensure it works properly, you need to make sure that the uninstall webhook calls the themeFileDelete function correctly. The webhook needs to trigger the file deletion logic as part of the uninstallation process.
Here's an updated approach with a few adjustments:
Webhook Setup: Ensure that the webhook for APP_UNINSTALLED triggers the themeFileDelete function as expected.
API Call: In the callback for the uninstall webhook, you can trigger the themeFileDelete function after receiving the uninstallation payload.
import { DeliveryMethod } from "@shopify/shopify-api"; import themeFileDelete from './index.js'; export default { // Other webhooks... /** * Webhook for when the app is uninstalled */ APP_UNINSTALLED: { deliveryMethod: DeliveryMethod.Http, callbackUrl: "/api/webhooks", callback: async (topic, shop, body, webhookId) => { const payload = JSON.parse(body); console.log("Payload on app uninstall:", payload); console.log("Topic:", topic); console.log("Shop:", shop); console.log("Webhook ID:", webhookId); // Trigger the theme file deletion process try { await themeFileDelete(); // Ensure this function handles file deletion logic } catch (error) { console.error("Error during file deletion:", error); } } } };
By setting this up correctly, the theme files (such as index3.liquid in your example) will be deleted when the uninstall webhook is triggered.
I manually call the "themeFileDelete " function on a button click, and the file is deleted, but it is not being called in the webhook. I have tried many times.
@rohit1 This is the merchant app forums not developer api support.
use the community.shopify.dev api developer forums.
Convert app to use app blocks when possible.
The uninstalled webhook is uninstalled. not "uninstalling".
..ed is PAST TENSE, it's already happened.
The app and authorization scopes are gone.
And yes the shopify docs on this are below subpar for the authorization process and every other system touched by changes needing removal upon uninstallation, the omission of this very important fact of the processes arrow-of-time is a bit absurd.
This is why some apps use an pre-uninstall process built into the app that merchants can run in the app and not using the shopify admin uninstall process exclusively.
The rest is pretty much chatgpt generated misinformation making you chase your own tail.
Contact paull.newton+shopifyforum@gmail.com for the solutions you need
Save time & money ,Ask Questions The Smart Way
Problem Solved? ✔Accept and Like solutions to help future merchants
Answers powered by coffee Thank Paul with a ☕ Coffee for more answers or donate to eff.org
Hey Community! As we jump into 2025, we want to give a big shout-out to all of you wh...
By JasonH Jan 7, 2025Hey Community! As the holiday season unfolds, we want to extend heartfelt thanks to a...
By JasonH Dec 6, 2024Dropshipping, a high-growth, $226 billion-dollar industry, remains a highly dynamic bus...
By JasonH Nov 27, 2024