Can't create recurring charge due to 'X-Frame-Options = deny'.

1 0 1



I am trying to create a recurring charge in an embedded app created in Node.js and based on Express. Everything works perfectly until step 3 - these steps - where Shopify is redirecting the merchant to accept or decline the charge. It is simply not allowed because the app is embedded. In the console I get the following error:


Refused to display 'confirmation_url' in a frame because it set 'X-Frame-Options' to 'deny', where I've removed the confirmation_url for readability.


How do I circumvent this? It looks like I'm not the only one who has had this problem, so it is probably a problem that should be addressed in the documentation.

All the best,

Replies 5 (5)

Shopify Staff (Retired)
628 49 110

Hi @mfvas,


You need to do a top level redirect that escapes the iframe when redirecting the merchant to the confirmation url. There's an explanation in our oAuth documentation that also applies here:


Since the application is loaded inside an iframe, it is critical that the initial OAuth redirect to Shopify occurs at the parent level, escaped from the iframe. Shopify returns the X-Frame-Options=DENY header and prevents any Shopify admin pages from being loaded inside an iframe. The Embedded App SDK provides a method that can be used to perform a redirect within the parent window.

To learn more visit the Shopify Help Center or the Community Blog.

Shopify Partner
5 1 12

Hi, you can do a top level page redirect to bypass this-
Instead of doing 
`window.location.href =;`

` =;`

Shopify Partner
134 5 29

@Pritam_Roy 's comment works!

Not applicable

Thank you @Pritam_Roy  !

Shopify Partner
215 3 97

I was stuck on this for awhile too. I wanted to offer multiple plans, but the Shopify app tutorial doesn't provide that example, and neither does the documentation on

Below is an example using React & the AppBridge component:


NOTE: in the Shopify app tutorial example, the server redirects the client to the appSubscriptionCreate's confirmationURL. Instead you'll need to have your server return the confirmationURL in a string format. That way you can escape the iframe your app is embedded in and resolve the X-Frame-Options issue.

import { Page } from '@shopify/polaris'
import createApp from '@shopify/app-bridge';
import { Redirect } from '@shopify/app-bridge/actions';
import Cookies from "js-cookie";
import axios from 'axios';

export default function Plans() {
  const app = createApp({
    apiKey: API_KEY,
    shopOrigin: Cookies.get('shopOrigin'),

  const redirect = Redirect.create(app);

  function openPlan(planUrl) {
      .then((res) => {
        redirect.dispatch(Redirect.Action.REMOTE, { url:, newContext: false })
      .catch(err => { console.log(err) })

  return (
      Pick plan:

      <button onClick={() => { 
      <button onClick={() => { 
      <button onClick={() => { 
Founder of Real ID - Verify your customer's real IDs easily & securely with modern A.I.

Want to see it in action? Check out our demo store.