This is unoffical sample code for scratch building Shopify app without CLI automatic cocde generation for learing how it works with simple React and GraphQL knowledge.
Making clear, simple, and fewest code is this purpose that's why it doesn't use the CLI generated code.
Reading Shopify OAuth flow might help you to grab the basic.
For quick start with automatically generated code, go to the official CLI tutorial.
--------- Backend process in a server (Node.js) ---------
app.js ... Koa Node.js app for backend for app install endpoints, GraphQL API calls, and DB access, etc. No Shopify libraries or CLI generated code used.
package.json ... app.js used npm libaries and scripts for building and running this app.
views/ ... holds Koa Node.js dynamic rendering htmls. This is a SPA app which uses index.html only generated by Vite build in frontend.
./index.html ... Koa top page view rendered by app.js server code (for code running, this needs replaced with Vite built one).
public/ ... holds static files hosted by app.js server code (for code running, this needs replaced with Vite built one).
--------- Frontend UI in a browser (React) ---------
frontend/ ... React code base to be built by Vite for app admin UI. All built code runs at the client = browser as minized JS + CSS.
./src/ ... React source code with JSX of Shopify App Bridge + Polaris.
./index.html ... replaces views/index.html as a Vite built file which renders the root React compoment.
./public/ ... Static files used by React code.
./package.json ... React code used npm libraries and scripts for building React code with Vite.
./vite.config.js ... Vite congfig file for building React code into real runnable minized JS + CSS on browsers.
--------- Extensions with Shopify CLI generation and deployment (Liquid/JavaScript/Wasm, etc.) ---------
extensions/ ... automatically generated directory and code by Shopify CLI `npm run generate extension`.
./my-theme-app-ext ... Theme App Extensions sample following this turotial. https://shopify.dev/apps/online-store/theme-app-extensions/getting-started
./my-function-discount-ext ... Shopify Functions for Dicounts Extensions sample using Cargo with Rust https://shopify.dev/apps/discounts/create#step-4-add-and-deploy-a-product-discount-extension
./my-function-shipping-ext ... Shopify Functions for Delivery Extensions sample using Cargo with Rust https://shopify.dev/apps/checkout/delivery-customizations/getting-started
./my-function-payment-ext ... Shopify Functions for Payment Extensions sample using Cargo with Rust https://shopify.dev/apps/checkout/payment-customizations/getting-started
shopify.app.toml ... required file by CLI commands.
React (JSX, Props, State, Hooks, etc.) and GraphQL (Query, Edges, Union, etc.) are mandatory technologies for manipulating this sample.
For creating React frontend, the following contents might help you.
For extensions like Admin Link, Theme App Extensinons, Shopify Functtions, and Checkout Extensions, refer to the app extensions page.
In this sample, CLI generated extensions are given the following patch to fit to the existing non-CLI-generated codes.
1. Execute `npm install --save @shopify/app @shopify/cli` instead of `npm init @shopify/app@latest`, to add those library to 'package.json' dependencies only, to avoid overwriting the exising code.
2. Copy the following script to "scripts" in 'package.json' to execute extension commands from the result of `npm init @shopify/app@latest` in another directory.
"shopify": "shopify",
"dev": "shopify app dev",
"info": "shopify app info",
"generate": "shopify app generate",
"deploy": "shopify app deploy"
3. Copy 'shopify.app.toml' to the root path from the result directory above too.
4. To register extensions to new apps from exsiting codes in '/extensions/', execute `npm run deploy -- --reset` to make a draft extension, and enable "Development Store Preview" in the created extension in your partner dashboard
(NOTE THAT `npm generate extension` is for the initial code generation only, not required for the extension registration or push).
- Add the following environmental variables locally or in cloud platforms like Render / Heroku / Fly, etc.
SHOPIFY_API_KEY: YOUR_API_KEY (Copy and paste from your app settings in partner dashboard)
SHOPIFY_API_SECRET: YOUR_API_SECRET (Copy and paste from your app settings in partner dashboard)
SHOPIFY_API_VERSION: unstable
SHOPIFY_API_SCOPES: write_products,write_discounts,read_orders,write_payment_customizations,write_delivery_customizations,write_pixels,read_customer_events,write_customers,write_metaobject_definitions,write_metaobjects
SHOPIFY_DB_TYPE: MONGODB (Default) / POSTGRESQL / MYSQL
// The followings are required if you set SHOPIFY_DB_TYPE 'MONGODB'
SHOPIFY_MONGO_DB_NAME: YOUR_DB_NAME (any name is OK)
SHOPIFY_MONGO_URL: mongodb://YOUR_USER:YOUR_PASSWORD@YOUR_DOMAIN:YOUR_PORT/YOUR_DB_NAME
// The followings are required if you set SHOPIFY_DB_TYPE 'POSTGRESQL'
SHOPIFY_POSTGRESQL_URL: postgres://YOUR_USER:YOUR_PASSWORD@YOUR_DOMAIN(:YOUR_PORT)/YOUR_DB_NAME
// The followings are required if you set SHOPIFY_DB_TYPE 'MYSQL'
SHOPIFY_MYSQL_HOST: YOUR_DOMAIN
SHOPIFY_MYSQL_USER: YOUR_USER
SHOPIFY_MYSQL_PASSWORD: YOUR_PASSWORD
SHOPIFY_MYSQL_DATABASE: YOUR_DB_NAME
// The followings are required if you use `webhookcommon` endpoint as a manually created webhook target.
SHOPIFY_WEBHOOK_SECRET: YOUR_TEST_STORE_WEBHOOK_SIGNATURE given by the webhook creation settings
- Build and run the app server locally or in cloud platforms. All settings are described in
package.json
(note that the built React code containsSHOPIFY_API_KEY
value from its envrionment variable, so if you run it with your own app, you have to run the build command below at least one time).
Build command = npm install && npm run build (= cd frontend && npm install && npm run build && rm -rf ../public && mv dist ../public && mv ../public/index.html ../views/index.html *Replacing Koa view files with Vite buit code)
Start command = npm run start (= node app.js)
- If you run locally, you need to ngrok tunnel for public URL as follows (otherwise, the command lines above are usable in Render or other cloud platform deploy scripts).
cd NGROK_DIR && ngrok http 3000
-
Set
YOUR_APP_URL
(your ngrok or other platformroot
URL) andYOUR_APP_URL/callback
to your app settings in partner dashboard. If you add?external=true
parameter toYOUR_APP_URL
, the app UX turns into a service connector which tries to connect Shopify stores with their users. -
(For PostgreSQL or MySQL users only,) create the following table in your database (in
psql
ormysql
command or other tools).
For PostgreSQL:
CREATE TABLE shops ( _id VARCHAR NOT NULL PRIMARY KEY, data json NOT NULL, created_at TIMESTAMP NOT NULL, updated_at TIMESTAMP NOT NULL );
For MySQL:
CREATE TABLE shops ( _id VARCHAR(500) NOT NULL PRIMARY KEY, data JSON NOT NULL, created_at TIMESTAMP NOT NULL, updated_at TIMESTAMP NOT NULL );
-
For CLI generated extensions, execute
npm run deploy -- --reset
and follow its instruction (choose your partner account, connecting to the exising app, etc.) which registers extensions to your exising app and create/.env
file which has extensiton ids used by this sample app. After the command ends successfully, go to the created extension in your partner dashboard and enable its dev. preview if available (it's enough for testing in development stores). For Shopify Functions deployment using Rust, you need Cargo Wasm package installed first bycargo install cargo-wasi
. -
For updating the extensions, execute
npm run deploy
(without-- --reset
) to apply (upload) your local modified files to the created extensions (-- --reset
is used for changing your targeted app only). -
(For live stores only, you need to create a version of the extension and publish it. See this step.)
Access to the following endpoit.
https://SHOPIFY_SHOP_DOMAIN/admin/oauth/authorize?client_id=YOUR_API_KEY&scope=YOUR_API_SCOPES&redirect_uri=YOUR_APP_URL/callback&state=&grant_options[]=
ใ
Or
you can install to your development stores from the app settings in partner dashboard.
All sample videos are available at Wiki.
- Session Token: '/sessiontoken'
- What's App Bridge session token about and how the authenticated request works.
- Admin Link: '/adminlink'
- How to manage and protect admin links regardless of embedded or unembedded.
- Theme App Extension: '/themeappextension'
- Basis usage in combination with App Proxies and Theme Editor
- Function Discount: '/functiondiscount'
- Discount implementation by Shopify Functions in combination with customer metafields
- Function Shipping: '/functionshipping'
- Shipping rate filtering by Shopify Functions with input zip codes
- Function Payment: '/functionpayment'
- Payment method filtering by Shopify Functions with selected shipping rates
- Web Pixel: '/webpixel'
- Checking customer events in a browser console to send them to GA4 Data Streams
- Post Purchase: '/postpurchase'
- Switching upsell products and getting shop review scores with product and customer metafields
- Checkout Extension: '/checkoutextension'
- Reproducing upsell and reviews of post-purchase during checkout with IP address blocking
- Fulfillment: '/fulfillment'
- How to create and control fulfillments (shipping) via API for a specific order (TBD)
- Transaction: '/transaction'
- How to create and control transactions (payments) via API for a specific order (TBD)
- Metaobject: '/metaobject'
- Basic usage (TBD)
- Multipass: '/multipass'
- Simple SSO login implementation (TBD, Plus only for live)
- B2B: '/b2b'
- Sample for creating a company and its onwed customers for B2B checkout (TBD, Plus only for live)
- Bulk Operation: '/bulkoperation'
- Creating large size of data for testing and learing how to manage bulk operation. (TBD)
- ShopifyQL: '/shopifyql'
- Your own ShopifyQL notebook with API. (TBD)
- Marketing Activity: '/marketingactivity'
- Basic usage. (TBD)
- Tokengating: '/tokengating'
- Basic usage. (TBD)
- If you see the error page with the message like
"YOUR_APP_NAME is expired, this is an old app which no logner works after..."
during top page rendering in Shopify admin, check and fix the following major issues.- Do not use redirection to the old admin URL of "https://XXX.myshopify.com/admin". Use the new one of "https://admin.shopify.com/store/XXX", instead. Refer to the migration document.
- Your server needs to render the top page at acceptable speed in the right way. Too slow access, error HTTP codes, or server shutdown causes the error above in live stores (not in development ones). Some cloud plarform like Render, Heroku, etc do the very slow response for the first time in a while with free plans, so you need to swtich to ngrok hosting or pay those services for higher performence.
- You can use the endpoint of
webhookgdpr
for GDPR Webhooks. - If you fail to get protected customer data in Checkout UI Extension or API Webhook creation even in dev. stores, submit your app first which enable you get them.
- This code is fully unofficial and NOT guaranteed to pass the public app review for Shopify app store. The official requirements are described here.
- You need to follow Shopi API Licene and Terms of Use even for custom app usage.