App reviews, troubleshooting, and recommendations
We're moving the community! Starting July 7, the current community will be read-only for approx. 2 weeks. You can browse content, but posting will be temporarily unavailable. Learn more
I am trying to figure out how to pass data between the theme-app-extension and the backend of the application that the theme-app-extension is connected to. The theme-app-extension is all liquid, css, and javascript so I wasn't sure if there was a built in way to pass data between the two. For example is there a suggested method to pull data into the theme-app-extension from the database and is there a suggested way to send data to the database from the code running the theme-app-extension? I am fairly new to doing anything with theme-app-extensions as well as building Shopify applications. I have built Shopify applications that was admin facing or just cosmetic, this is my first time building a Shopify application that takes user input and sends it to the database and retrieves that data for the end-user to see.
Any suggestions would be greatly appreciated.
Thank You.
For anybody else reading this in the future with the same problem.
The answer is to use shopify app proxies, https://shopify.dev/apps/online-store/app-proxies
a rough outline of the steps I took to do this.
I don't really know but the way I got it to work was just by putting the ngrok url (APP URL) in the App Proxy proxy url field in the APP SETUP panel. in the subpath prefix I put apps and in the subpath field I put the app name. That worked for me and I am able to send data from the theme-app-extensions to the backend api route and save the data into the database and retrieve that data for the shopify admin area dashboard. Let me know if this helps or not.
Hello Jameshagood, your answers are very helpful.
The ngrok URL changes frequently, do you update the APP URL manually? If not, how do you handle this change? Do you think using the ngrok URL would work in production?
yes I update every time it changes which is like once a day. The app I am building isn't in production yet but in production you should just be able to put whatever the URL is for the app once it is on servers somewhere with a HTTPS URL
I have built a couple different shopify apps when I was trying to learn how to do it, so I have never put one in production. the one I am currently building will be my first live shopify application that I built.
This sounds very helpful! Exactly same question I had, I was wondering if you know anything about this but when I make a fetch request like shown in the video, it routes to a different ip address then ngrok even if I added that in the proxy configuration. Did you ever get that? I am perhaps starting my app wrong.
Hello James, could you provide some insight into the naming of routes and the verification of incoming requests from the proxy. I have followed the same steps, I am able to send a request to the app-proxy but unable to get it through to the backend api. I receive no errors It simply doesnt connect to the backend.
This has been a little while ago since I done this. I looked at the code I had to see the routes I had set up and I had a POST route to /proxy
@jameshagood Thanks for sharing your knowledge with the community, I am still facing the same issue and have posted the details here - https://github.com/Shopify/shopify-api-js/issues/802
Could you please have a look and if possible can you share snippet code which worked for you ?
Thanks
I managed to get everything working by simply deploying the app to gcp, the proxy requests simply wouldn't go through for a ngrok url, initially they were blocked by ngroks default browser check but even disabling that changed nothing. So the routes were defined correctly only to begin with thus no blockers on that front.
I managed to get things working as well:
The only question, that I have is, how do I get the Theme App Extension to work with two different App Proxies?
Essentially, I have a development [app bridge] & production version [fly.io] of my app.
I have the same Theme App Extension, embedded in both apps.
Each app has a different App Proxy URL value.
When I try and send the data to my development version of the Remix App, everything works fine.
When I try and send the data to my production Remix App on fly.io, it keeps trying to send it to my development App Proxy URL, even though I have definitely set the two different App Proxy URLs, correctly.
Now, it seems like the Theme App Extension is agnostic with respect to the URL that is used, within the fetch() method.
This fetch() method param URL is:
online store address + the proxy prefix + proxy subpath
Essentially, the fetch() method URL param, is the same for both the development & production app.
It should then be able to work out which environment it is in, by referring to it's parent app. It should then be able to access the correct App Proxy URL.
It then transfers the data from the online store address URL, to the App Proxy URL.
But, my system seems to fail, at this transfer point.
Does anyone know how to resolve this?
i can't send data from my sign up form to back end, could you tell me how?
OK. The first thing to do, is to get your App Proxy setup correctly.
I am assuming you have created some kind of form, in your Theme App Extension. You need to make sure that you use something like fetch() or axios() to post your data to your Admin App.
App Proxy setup:
You should point the proxy at a Remix route, so, for example:
app/routes folder:
app.api.jsx
Then the App Proxy URL would be:
https://mydomain.trycloudflare.com/app/api
Then your fetch() URL would be like:
/subpath_prefix/subpath[/route_path]
So let’s say your subpath_prefix value is apps and your subpath is app-proxy, then the form action or fetch() URL will be:
/apps/app-proxy/api
So what actually happens when the data is posted by a fetch() XHR request? Well, the request is intercepted by Shopify and the URL is analysed to see if it matches an App Proxy value. If there is a match, the data is forwarded to the App Proxy proxy URL value. Then, query params are added onto the end of the proxy URL.
These params include:
Example:
GET /?index=value&example.myshopify.com&logged_in_customer_id=1234567890&path_prefix=%2Fa%2Fexample×tamp=1234567890&signature=XXXXXXXXXX
The signature is important. It is made up of all the other query param values, which are sorted & then hashed. The signature is created using:
createSHA256HMAC()
https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/runtime/crypto/utils.ts#L6
App Proxy fetch() URL:
Note that, you don't have to add the domain part of the URL, in the fetch() URL param.
Please remember that form POST requests, hit the:
Remix action() method
And GET requests, hit the:
Remix loader() method
If you still have problems, let me know and I will go through other potential problems, including invalid signature.
I have this sign-up form in my app extension:
Try this:
fetch('/apps/proxytest', {
method: 'POST',
body: JSON.stringify(Object.fromEntries(formData)),
headers: {
'Content-Type': 'application/json
},
})
'Access-Control-Allow-Origin': '*',
export async function action({ request, params }) {
const { admin, session } = await authenticate.public.appProxy(request);
const formData = await request.json();
...
}
Thank you so much, my back now has data response. but why the field response is all null? please let mr know. i have console log all data but they are all null.
I think you need to use the name attribute in each form field like:
<input type="text" name="name" value="foo" />
If you want to collect form data via:
const formData = new FormData(form);
i have change like you said but the data return is always default value, even when i has change string in input form. The data request to back-ens always is:
13:44:00 │ remix │ {
13:44:00 │ remix │ name: 'foo',
13:44:00 │ remix │ email: 'foo',
13:44:00 │ remix │ mobile: 'foo',
13:44:00 │ remix │ address: 'foo',
13:44:00 │ remix │ gender: 'male'
13:44:00 │ remix │ }
this show even when i have used:
Are you using:
const formData = await request.json();
...
Inside your Remix App action() method, to parse the data?
This is very important.
yes i am using it
If this doesn’t work, I suggest removing:
const formData = new FormData(form);
And use something like:
const name = document.getElementById('name');
const email = document.getElementById('email');
…
const formData = JSON.stringify({
name: name.value,
email: email.value,
…
});
I only use:
new FormData()
For file uploads.
And finally, are you authenticating the request?
const { admin, session } = await authenticate.public.appProxy(request);
So, I have to find another way. Thank you for spending time helping me; I truly appreciate your support and guidance
No worries. I hope you find a solution soon..
There is one other angle, you might want to explore.
You can access Request Internals, by doing the following.
You might find the form data values, in here, as well:
export async function action({ request, params }) {
const { admin, session } = await authenticate.public.appProxy(request);
const formData = await request.json();
const sym = Object.getOwnPropertySymbols(request).find(
(s) => s.description === "Request internals"
);
let shop = "";
let customerid = "0";
let href = "";
let signature = "";
if(request[sym] && 'parsedURL' in request[sym] && 'href' in request[sym].parsedURL){
href = request[sym].parsedURL.href;
}
if(request[sym] && 'parsedURL' in request[sym] && 'searchParams' in request[sym].parsedURL){
const searchParam = request[sym].parsedURL.searchParams;
shop = searchParam.get('shop');
customerid = searchParam.get('logged_in_customer_id') || "0";
signature = searchParam.get('signature') || "";
}
...
}
Ok. i find out my problem. It seem a problem in my css file. When i remove my css it run normally. I have recieved data in back-end,. but now, how can i add data in back-end to my response
Maybe you need a liquid response?
https://shopify.dev/docs/api/shopify-app-remix/v2/authenticate/public/app-proxy#example-liquid
it's no use. In
You can’t return data like that. You have to use liquid
export const action = async ({request}) => {
const {storefront, liquid} = await authenticate.public.appProxy(request);
…
return liquid(erpData2.url_wchat);
}
Could you help me, why after i use return like you say, it has error 404 (Not Found) when i console.log(response). Could you help me show my url to my liquid code. i want to use it for an iframe
Well, the response gets sent back to the URL, that the request comes from.
Or are you saying that you want to return the response to a different URL?
i mean i want to send back response but how matter way i try, it still sat response 404 when i console.log my response
have you send back data to front end before, could you tell me how you do that?
Have you solved this. I am also stuck on the same problem.
My setup:
App proxy Subpath prefix : apps
App proxy Subpath : proxytest
Proxy URL: https://implications-lindsay-festival.trycloudflare.com/app/proxy
From theme app extension sending the request as :
const { admin, session } = await authenticate.public.appProxy(request);
if (session) {
console.log(session);
}
const response = await admin.graphql(
`#graphql
query productTitle {
products(first: 1) {
nodes {
title
}
}
}`,
);
I am able to fetch the product also, but not getting any response back.
In the browser it does 307 Temporary redirect to the <store-domain>/auth/login
You mean you are not able to send the response to the Theme App Extension page?
But anyway I think you need to do something like this:
const response = await admin.graphql( `#graphql query productTitle { products(first: 1) { nodes { title } } }`, );
const res = response.json();
return res;
It needs to return an object or an object in liquid format. But I think you maybe returning JSON.
Remix will convert the object to JSON for you.
yes not able to send the response to the theme app extension page
when clicking on the test button on the theme app extension page request is reaching to the remix app and I was able to call graphql query.
I think your fetch() URL might be wrong. How about:
fetch('/apps/proxytest/proxy')
I had already setup proxy with Subpath prefix as apps and subpath as proxy-1.when i am trying to access the data from application backend to my theme application by proxy api call ,the api is getting redirected itself and i am getting undifined data .
i want to send and retrieve data in shopify app extension using prisma but my data post is success but when i get data to show give error
this error below
Is shopify app proxy is working for customer order status page?