App Store Review Prompt
Merchants can leave an App Store review from the admin side menu or dashboard. An automatic prompt appears after the shop has used the app for three days, unless the merchant opts out.
Related: Recent storefront & admin changes
Entry points
Section titled “Entry points”| Location | Behavior |
|---|---|
| Side nav Rate & Review | Navigates to /app/review, which opens the App Store review URL in a new tab and returns to the dashboard. |
| Dashboard hero Rate & Review Our App | Opens the same URL in a new tab (window.open). |
| Auto modal Leave a review | Opens the same URL in a new tab; does not permanently dismiss the prompt. |
Constant: APP_STORE_REVIEW_URL in app/lib/app-store-review.server.js.
Automatic review modal
Section titled “Automatic review modal”Rendered globally from app/routes/app.jsx via app/components/AppStoreReviewModal.client.jsx.
When it shows
Section titled “When it shows”shouldShowReviewPrompt() returns true when all of the following hold:
shops.app_store_review_placed_atis null (merchant has not clicked Already Placed Review).- At least 3 days have passed since
shops.created_at(first install row create inensureShopRecord). - Either
shops.app_store_review_prompt_dismissed_atis null, or at least 3 days have passed since that timestamp.
Delay constant: REVIEW_PROMPT_DELAY_MS (3 × 24 hours) in app/lib/app-store-review.server.js.
Merchant actions
Section titled “Merchant actions”| Action | Effect |
|---|---|
| Leave a review | Opens App Store in new tab only. |
| Already Placed Review | Sets app_store_review_placed_at, clears dismiss timestamp, writes localStorage placed=1. Modal never shows again for that shop. |
| Close (X / backdrop) | Sets app_store_review_prompt_dismissed_at to now, writes localStorage dismissed-at. Modal hidden until 3 days later. |
Persistence API: POST /app/review-prompt with intent=placed or intent=dismiss (app/routes/app.review-prompt.jsx).
Database fields
Section titled “Database fields”On shops (migration 20260524120000_add_app_store_review_prompt):
| Column | Prisma field | Purpose |
|---|---|---|
app_store_review_placed_at | appStoreReviewPlacedAt | Permanent opt-out |
app_store_review_prompt_dismissed_at | appStoreReviewPromptDismissedAt | Snooze anchor for close/dismiss |
Install timing uses existing shops.created_at. Reinstall reactivates the same row, so the 3-day install delay is based on the original install date.
localStorage (per shop domain)
Section titled “localStorage (per shop domain)”Keys in app/lib/app-store-review-storage.js:
appifire-review:{shop}:placed—"1"when merchant clicked Already Placed Reviewappifire-review:{shop}:dismissed-at— ISO timestamp on dismiss (client cache; server is source of truth for snooze)
If the loader reports appStoreReviewPlacedAt, the client syncs the placed flag on mount to avoid a flash before the next request.
Local testing
Section titled “Local testing”Temporarily lower REVIEW_PROMPT_DELAY_MS, or adjust created_at / app_store_review_prompt_dismissed_at in the database for a test shop.
npx prisma migrate deploy