For discussing the development and usage of Checkout UI extensions, post-purchase extensions, web pixels, Customer Accounts UI extensions, and POS UI extensions
Hello there, people
I am trying to develop an app, which the main goal would be that, based on the customer's choices on the product's form, the price would change, and the final price would be available for them to see (I can't use Shopify's native variants. It's with dimensions, and there are not fixed numbers). Visually, I already know how to do that, but, for the product to go to the cart with the adequate price, I was thinking that I would need a funcion to create a specific variant for the customer's choices and final price, and, then, delete the variant after the order was created.
The thing is, I am trying to get from the documentation what do I need to create to implement this functionality, that wouldn't have any settings, it would just be a code that needs to watch the changes that the customer does and creates the variant, but I am not understanding which of the extensions that I can generate would work for that. If it is, indeed, through an app extension and not somewhere else in the code from the app, but I don't know where it would be, since I don't have access to theme code in the app's original architecture.
Any help would be greatly appreciated, thanks
Solved! Go to the solution
This is an accepted solution.
In case anyone ends up here needing this answer, I was able to create the needed 'session' variant by importing these in the page that I wanted '/variant-creator':
import "@shopify/shopify-api/adapters/node";
import {
LATEST_API_VERSION,
} from "@shopify/shopify-app-remix/server";
import { shopifyApi, ApiVersion, Session } from "@shopify/shopify-api";
import { restResources } from "@shopify/shopify-api/rest/admin/2023-07";
and then, in the action function of the page (I'm using Remix):
export const action = async ({ request }) => {
const sess = await shopify.sessionStorage.findSessionsByShop(request.host);
const shopifyAdmin = shopifyApi({
apiKey: process.env.SHOPIFY_API_KEY,
apiSecretKey: process.env.SHOPIFY_API_SECRET, // Note: this is the API Secret Key, NOT the API access token
apiVersion: LATEST_API_VERSION,
isCustomStoreApp: true, // this MUST be set to true (default is false)
adminApiAccessToken: sess[0].accessToken, // Note: this is the API access token, NOT the API Secret Key
isEmbeddedApp: true,
hostName: process.env.SHOPIFY_APP_URL,
// Mount REST resources.
restResources,
});
const session = shopifyAdmin.session.customAppSession("my-store.myshopify.com");
const productCount = await shopifyAdmin.rest.Product.count({
session: session,
});
As for where request.host, process.env.SHOPIFY_APP_URL and 'my-store.myshopify.com' are used, I honestly don't know if I used the correct urls on each one, if the url from the host of the request should be where the env variable is and so on, but this way worked, so I am keeping like this currently
Hi Uhrick,
Based on your requirements, you might want to create a custom app that makes use of Shopify’s Admin API. Specifically, you would be using the ProductVariant
resource to dynamically create and delete product variants based on the customer's selections.
Here's a general idea of how you could implement this:
Add an event listener to the product form on your theme that triggers whenever the customer makes a selection. This can be done using JavaScript in your theme code.
When a selection is made, this triggers a request to app's backend. The request would include details of the customer's selections.
Your app's backend would then make a POST request to Shopify's Admin API to create a new variant with the appropriate price. The API endpoint you'd use is /admin/api/2023-10/products/{product_id}/variants.json
, replacing {product_id}
with the ID of the product being customized. You would include the details of the new variant (including its price) in the body of the request.
Once the variant is created, its ID is returned in the API response. You would then use this ID to update the product form on your theme, so that when the customer adds the product to their cart, they're actually adding the newly created variant.
After the order is created, you would make a DELETE request to the Admin API to delete the temporary variant. The endpoint is /admin/api/2022-01/products/{product_id}/variants/{variant_id}.json
, replacing {product_id}
and {variant_id}
with the appropriate IDs.
This is a simplified overview and might need to be adjusted based on your exact requirements and setup. Remember to handle potential errors and edge cases, such as what happens if the variant can't be created for some reason.
Also, please note that making a large number of API requests in a short amount of time can lead to hitting Shopify's rate limits, so you might want to implement some kind of rate limiting or caching strategy.
Hope this helps!
Liam | Developer Advocate @ Shopify
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution
- To learn more visit Shopify.dev or the Shopify Web Design and Development Blog
Hey, @Liam, thanks for the run through!
Just some follow up questions:
1 - Ok, so I don't even need an app extension, right? Just a javascript event on the theme code itself. But the thing is, I'm assuming that I would send this to one "actions" page of my app, such as '/webhooks', but how do I do that? Currently, as I'm developing, my app is hosted with a dynamic cloudflare url. How do I get the correct url to use from the theme? I think my sort of app can be hosted directly by Shopify, but I'm not sure if something like 'mystore.myshopify.com/app/testapp/wehooks' can be used.
2 - My problem with the variant resource (and a lot of other rest resources, actually) is the session, as seen in:
// Session is built by the OAuth process
const variant = new shopify.rest.Variant({session: session});
variant.product_id = 632910392;
variant.option1 = "Yellow";
variant.price = "1.00";
await variant.save({
update: true,
});
Shopiy's App template comes with an example use of webhooks in an action page 'webhooks,jsx', but it uses an 'authenticate.webhook()' function. I have tried multiple times checking shopify-app-remix documentation, and I can't find much info about different uses. So, what kind of request do I send from my store? A post request? And how do I treat it on my app so that I get this session that is needed for everything?
Thanks in advance!
@Liam Hello, were you able to seet this?
This is an accepted solution.
In case anyone ends up here needing this answer, I was able to create the needed 'session' variant by importing these in the page that I wanted '/variant-creator':
import "@shopify/shopify-api/adapters/node";
import {
LATEST_API_VERSION,
} from "@shopify/shopify-app-remix/server";
import { shopifyApi, ApiVersion, Session } from "@shopify/shopify-api";
import { restResources } from "@shopify/shopify-api/rest/admin/2023-07";
and then, in the action function of the page (I'm using Remix):
export const action = async ({ request }) => {
const sess = await shopify.sessionStorage.findSessionsByShop(request.host);
const shopifyAdmin = shopifyApi({
apiKey: process.env.SHOPIFY_API_KEY,
apiSecretKey: process.env.SHOPIFY_API_SECRET, // Note: this is the API Secret Key, NOT the API access token
apiVersion: LATEST_API_VERSION,
isCustomStoreApp: true, // this MUST be set to true (default is false)
adminApiAccessToken: sess[0].accessToken, // Note: this is the API access token, NOT the API Secret Key
isEmbeddedApp: true,
hostName: process.env.SHOPIFY_APP_URL,
// Mount REST resources.
restResources,
});
const session = shopifyAdmin.session.customAppSession("my-store.myshopify.com");
const productCount = await shopifyAdmin.rest.Product.count({
session: session,
});
As for where request.host, process.env.SHOPIFY_APP_URL and 'my-store.myshopify.com' are used, I honestly don't know if I used the correct urls on each one, if the url from the host of the request should be where the env variable is and so on, but this way worked, so I am keeping like this currently