AstroBaaS

Catalogue & product data

Product Inquiry Form

Free — GPL coresize Mplanned, not built

Generated from docs/plan/core/product-inquiry-form/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.

Core form-collection feature enabling customers to ask questions about products (sizing, compatibility, stock) without placing an order. A small form (question + optional name/email) embedded on product pages, stored in a product-specific inbox. Reduces checkout abandonment when customers have last-minute questions. This is foundational; AI-powered auto-responses belong in a paid tier.

The problem

Customers can’t ask questions about products (sizing, compatibility, stock); merchants lose sales when customers abandon due to uncertainty.

What it does

  • Product inquiry form: question (required, max 1000 chars), optional name, optional email, optional phone, embedded on product pages
  • CAPTCHA protection: reCAPTCHA v3 or hCaptcha, configurable by merchant
  • Form submission storage: product_inquiry (id, product_id, question, name, email, phone, submitted_at, ip_address, status: ‘new’ | ‘answered’ | ‘archived’)
  • Merchant notification: email sent to merchant when a new inquiry is submitted
  • Customer notification: if email provided, send ‘We received your question’ confirmation
  • Product-specific inbox: admin can filter inquiries by product, see all questions about a specific SKU
  • Merchant reply: reply directly to an inquiry via admin panel; reply sent to customer’s email
  • Public Q&A (optional): merchant can mark a reply as ‘public’; question + answer appear on product page
  • Rate limiting: max 3 inquiries per customer IP per product per hour (configurable)
  • Spam filtering: reject inquiries with obvious spam patterns
  • Webhook on new inquiry: plugin can listen to ‘product.inquiry’ event
  • Export inquiries: CSV export of inquiries by product or date range

What it deliberately does NOT do

Each boundary carries its reason. A boundary without a reason gets crossed by the next person who reads this.

  • AI-powered auto-responses — that requires ML and external API; manual replies only
  • Product specification auto-population — merchant must manually reference specs when replying
  • Inventory-aware responses (auto-reply ‘In stock’ if qty > 0) — merchant replies manually
  • Review/rating system — separate feature; this is Q&A only
  • Community Q&A moderation or voting — single-threaded merchant-reply only, no voting

Data model

New entity: product_inquiry (id, product_id: foreign key, question: string, name: string (nullable), email: string (nullable), phone: string (nullable), submitted_at: timestamp, ip_address: string, status: ‘new’ | ‘answered’ | ‘archived’, public_reply: string (nullable), is_public: boolean, merchant_reply_sent_at: timestamp (nullable), merchant_reply_from: user_id (nullable)).

API

  • POST /products/:id/inquiries — submit a product inquiry {question, name?, email?, phone?}, return {success: boolean, inquiry_id: string}
  • GET /products/:id/inquiries — list inquiries for a product (admin only), optionally include public ones (no auth)
  • GET /inquiries — list all product inquiries (admin only), paginated and filterable by status, date, product
  • GET /inquiries/:id — retrieve a single inquiry (admin only or inquiry author with token)
  • POST /inquiries/:id/reply — submit a merchant reply (admin only), optionally mark as public
  • PUT /inquiries/:id/status — update status to ‘answered’ or ‘archived’ (admin only)
  • GET /inquiries/export — export inquiries as CSV (admin only)

Every route added here must also appear in src/pages/openapi.json.ts — a test fails the build if it does not.

Admin

Product inquiry management: (1) Inbox view (all inquiries across all products, mark as answered/archived), (2) Product inquiry view (filter by product, see all questions about a SKU), (3) Reply form (text area, checkbox to make public), (4) Public Q&A preview (see which inquiries are published on product page), (5) Settings (CAPTCHA keys, notification email, rate limit, spam filters), (6) Stats (inquiries per product, avg response time).

The seam — why this is core

Core owns the inquiry form, storage, notification, and reply mechanism. Merchants can use this standalone without paid tiers. Paid tier could own auto-responses (AI-powered or template-based), smart routing (route sizing questions to inventory team), and community voting/moderation.

Core owns the interface + honest form collector; product inquiry is basic storefront infrastructure, not a credential or support commitment.

Dependencies

  • product-management (core; inquiries are attached to products)
  • email-layer (core; to send notifications and replies)
  • captcha-integration (core; to protect form from spam)

Acceptance checks

Each of these must be able to fail. Before claiming this is done, break the code deliberately and watch each one go red.

  • A POST /products/abc123/inquiries with question=‘What size for a 6-year-old?’ stores the inquiry and sends a notification email to the merchant.
  • If email is provided, a confirmation email is sent to the customer (‘We received your question about Product X’).
  • GET /products/abc123/inquiries (no auth) returns only inquiries marked is_public=true, with question + public_reply visible.
  • Merchant replies via admin panel; reply is sent to customer’s email and inquiry.status changes to ‘answered’.
  • Checking the ‘Make public’ checkbox when replying publishes question + answer on product page (is_public=true).
  • Rate limiting rejects a fourth inquiry from the same IP for the same product within an hour, returning 429.
  • Spam filter rejects inquiry with question=‘BUY VIAGRA’, logs it, does not store.
  • Exporting inquiries as CSV includes product_id, question, name, email, submitted_at, is_public, public_reply columns.

Risks

If merchant replies are not monitored, customers think their questions were ignored. A public Q&A that shows out-of-date or incorrect product info (e.g., ‘In stock’ but product is discontinued) misleads shoppers. If CAPTCHA fails, bots flood inquiries. A merchant who accidentally marks a private reply as public exposes internal notes or errors to the public.

Commercial context

Suggested pricefree (core)
Rival anchorShopify: Product Reviews app (free); Magento: included

The anchor is what the nearest equivalent charges on Shopify or Magento today. It is context for a pricing decision, not the decision.


Generated from the commerce plan. See docs/COMMERCE-PLAN.md for the full catalogue and ../../AI-GUIDE.md for how to work on this repository.