Testing Up to Phase 2 (Product Sync & Ingestion)
This guide explains how to test the app through Phase 0, 1, and 2: OAuth, session storage, shop persistence, product sync, and ingestion (chunks + embeddings). Use it after you have implemented Phase 0–2.
1. Prerequisites
Section titled “1. Prerequisites”Before testing, ensure:
| Item | Action |
|---|---|
| Database | Postgres with pgvector is running (e.g. Dokploy). Migrations applied: cd appifire-ai-chat && npx prisma migrate deploy |
.env | In appifire-ai-chat/, copy .env.sample to .env and set: DATABASE_URL, DIRECT_URL, SHOPIFY_API_KEY, SHOPIFY_API_SECRET, SCOPES, SHOPIFY_APP_URL, and OPENROUTER_API_KEY (required for embeddings in Phase 2). |
| Shopify | Partner account + at least one development store with some products (even 1–2 is enough). |
| Shopify CLI | Logged in: shopify login (same email as Partner account). |
2. Run the app locally
Section titled “2. Run the app locally”From the app folder:
cd appifire-ai-chatnpm installnpx prisma generatenpm run devThis runs shopify app dev: it starts the Remix server and opens a tunnel. The CLI will print a URL like https://xxx.trycloudflare.com or similar — that is your app URL for this session.
- If the Partner app is still using a fixed URL (e.g.
https://ai-chat.appifire.com), install/re-auth will hit that URL. For local testing you need the app to be reachable at the tunnel URL. Either:- In Partner Dashboard → your app → App setup → set App URL to the tunnel URL shown by
shopify app devfor this run, or - Use the CLI’s “Preview URL” to install the app (the CLI often gives you a link that uses the tunnel).
- In Partner Dashboard → your app → App setup → set App URL to the tunnel URL shown by
- When you install or re-authorize the app on a dev store, the browser will go through OAuth and then load the app. That triggers
afterAuthand thus the full product sync in the background.
3. Trigger product sync
Section titled “3. Trigger product sync”Sync runs automatically in two cases:
- Install — When a merchant installs the app (OAuth completes),
afterAuthruns and callssyncAllProducts({ shopId, admin }). - Re-auth — If the app was already installed and you change scopes or re-open the app and Shopify re-runs OAuth,
afterAuthruns again and sync runs again.
How to trigger it:
- First time: In the Partner Dashboard, open your app → Test your app (or use the install link for your dev store). Complete install; the tunnel must be the app URL as in step 2.
- Re-trigger: Uninstall the app from the dev store, then install again. Or use “Test your app” again if the CLI offers a new session.
Sync is fire-and-forget: the OAuth callback returns immediately; sync and ingestion run in the background. So you verify via logs and database, not the browser.
4. Check logs
Section titled “4. Check logs”In the terminal where npm run dev is running, look for:
[afterAuth] Shop upserted: your-store.myshopify.com (id: ...)
→ Shop record created/updated.[product-sync] Starting full sync for shop ..., job ...
→ Sync started.[product-sync] Found N products to sync
→ Products fetched from Shopify.[product-sync] Completed sync for shop ...: N/N products
→ Sync finished.- Any
[product-sync] Failed to sync product ...or[afterAuth] product sync failed:
→ Investigate (e.g. missingOPENROUTER_API_KEY, DB or API errors).
If you see “Found 0 products”, add at least one product in the dev store (Products → Add product) and trigger sync again (re-install or re-auth).
5. Verify in the database
Section titled “5. Verify in the database”Use either Prisma Studio or SQL.
Option A: Prisma Studio
Section titled “Option A: Prisma Studio”cd appifire-ai-chatnpx prisma studioThen:
| Table | What to check |
|---|---|
Shop | One row for your dev store; shopDomain, accessToken (non-empty), status: active. |
Product | Rows per Shopify product; shopId = that shop’s UUID; shopifyProductId, title, etc. |
ProductVariant | Rows per variant; productId matches Product.id. |
KnowledgeSource | One row per shop with type: 'product' (or as in your code). |
KnowledgeDocument | One row per product; sourceId = that source; externalRefId = Shopify product ID. |
KnowledgeChunk | Chunks for each document (overview + variant chunks). |
Embedding | One row per chunk; embedding is a vector (in Studio you may see “[object]” or similar). |
IngestionJob | Latest job for the shop: status: 'completed', totalDocuments / processedDocuments = product count. |
Option B: SQL (e.g. psql or Dokploy SQL console)
Section titled “Option B: SQL (e.g. psql or Dokploy SQL console)”-- ShopsSELECT id, "shopDomain", "plan", status FROM shops;
-- Product count per shopSELECT s."shopDomain", COUNT(p.id) AS productsFROM shops sLEFT JOIN products p ON p."shopId" = s.idGROUP BY s.id, s."shopDomain";
-- Chunks and embeddings per shopSELECT s."shopDomain", COUNT(DISTINCT kd.id) AS documents, COUNT(kc.id) AS chunks, COUNT(e.id) AS embeddingsFROM shops sJOIN knowledge_sources ks ON ks."shopId" = s.idJOIN knowledge_documents kd ON kd."sourceId" = ks.idLEFT JOIN knowledge_chunks kc ON kc."documentId" = kd.idLEFT JOIN embeddings e ON e."chunkId" = kc.idGROUP BY s.id, s."shopDomain";If sync and ingestion succeeded, you should see products, documents, chunks, and embeddings for your test shop.
6. Test product webhooks (optional)
Section titled “6. Test product webhooks (optional)”Phase 2 adds webhooks for product create/update/delete. To test:
- Create: In Shopify admin → Products → Add product. Save.
- In DB: new row in
Product,ProductVariant, and correspondingKnowledgeDocument/ chunks / embeddings (or updated if you use same externalRefId).
- In DB: new row in
- Update: Edit an existing product (title or description) and save.
- In DB:
Productand related chunks/embeddings updated (ingestion is idempotent via hash).
- In DB:
- Delete: Delete a product in Shopify admin.
- In DB: that product (and its variants) removed; cascades should remove related knowledge documents/chunks/embeddings if your schema uses
onDelete: Cascade.
- In DB: that product (and its variants) removed; cascades should remove related knowledge documents/chunks/embeddings if your schema uses
Webhooks are sent to your app’s public URL. So:
- Local: Use the same tunnel URL as in step 2 and ensure Shopify has that URL as the app URL (or that webhook subscription uses the tunnel). Shopify sends webhooks to the app URL (e.g.
https://your-tunnel.trycloudflare.com/webhooks/products/createetc.). - Deployed: Use
https://ai-chat.appifire.com(or your real app URL); webhooks go there.
Check logs for webhook requests; any 4xx/5xx will show in the terminal. You can also use Partner Dashboard → your app → Webhooks to see delivery status.
7. Common issues
Section titled “7. Common issues”| Symptom | Likely cause | Fix |
|---|---|---|
No [product-sync] logs | Sync not triggered or app URL not tunnel | Re-install app using tunnel URL; confirm afterAuth runs (you should see “Shop upserted”). |
| “Found 0 products” | Store has no products or API scope | Add a product in dev store; ensure read_products (and needed scopes) in shopify.app.toml and .env SCOPES. |
| Embeddings errors / 401 | OpenRouter key missing or invalid | Set OPENROUTER_API_KEY in .env; add credits in OpenRouter dashboard. |
| DB errors (e.g. unique constraint) | Schema/migration mismatch | Run npx prisma migrate deploy and npx prisma generate; ensure DB has pgvector and vector(1536) for embeddings. |
| Webhooks 404 | Wrong app URL or routes | Confirm app URL in Partner Dashboard matches where the app runs (tunnel or production); ensure routes exist: webhooks.products.create, webhooks.products.update, webhooks.products.delete. |
8. Quick checklist
Section titled “8. Quick checklist”-
.envhasOPENROUTER_API_KEY, DB URLs, and Shopify vars. -
npx prisma migrate deployandnpx prisma generaterun without errors. -
npm run devstarts; tunnel URL is used as app URL (or production URL) for install. - Install (or re-install) app on a dev store that has at least one product.
- Logs show “Shop upserted” and “Completed sync … N/N products”.
- In DB:
shops,products,product_variants,knowledge_*,embeddings,ingestion_jobslook correct. - (Optional) Create/update/delete a product and confirm DB and webhook logs.
Once this passes, you have verified the stack through Phase 2 and can proceed to Phase 3 (RAG & Chat API).