Developers using Shopify’s appPurchaseOneTimeCreate mutation in Remix.js apps encounter an X-Frame-Options error when redirecting users to the confirmation URL after clicking the purchase button. The error message indicates the confirmation URL is “denied by X-Frame-Options directive set to deny,” preventing the payment flow from completing within the embedded app frame.
Two working solutions have been identified:
Client-side redirect using top-level navigation:
top.location.href = res.confirmationUrl
This breaks out of the iframe restriction by redirecting the entire browser window.
Server-side redirect with _parent target (Remix-specific):
The root cause is Shopify’s restriction on opening new pages within embedded apps, requiring redirects to target the parent frame rather than the embedded iframe.
Summarized with AI on October 31.
AI used: claude-sonnet-4-5-20250929.
I am also experiencing an issue with the appPurchaseOneTimeCreate billing method in my Shopify app built with Remix.js. After the user clicks the purchase button, the appPurchaseOneTimeCreate mutation creates a confirmation URL, which I then attempt to redirect to. However, I encounter the following error:
The loading of “https://admin.shopify.com/store/demo-store/charges/ApplicationCharge/confirm_application_charge?signature=” in a frame is denied by “X-Frame-Options“ directive set to “deny“.
This issue is blocking our One Time Payment feature and affecting our users’ ability to complete the purchase process.
Can you provide guidance on how to resolve this issue? Is there a specific way to handle the redirection to the confirmation URL to avoid the X-Frame-Options restriction, or any alternative approach to ensure the payment process works seamlessly?
@Peterpot , I’m not sure but I think shopify doesn’t allow to open new page in embedded apps. You could try to redirect it in the parent frame. e.g. same like _parent behavior
If you’re using remix you can extract redirect from await authenticate.admin(request);