35 — TestimonialProductLink Model & Multi-Product Merchandising (Blueprint §5.9)
Cursor-ready plan for implementing optional secondary product links per submission, with admin UX, integrity rules, and storefront query behavior.
35 — TestimonialProductLink Model & Multi-Product Merchandising (Blueprint §5.9)
Section titled “35 — TestimonialProductLink Model & Multi-Product Merchandising (Blueprint §5.9)”Source: 02-Implementation-Blueprint.md — §5.9 New model: TestimonialProductLink.
This document is a build spec only. No code changes are implied until a task references this file.
Related: 10 (submission detail merchandising controls), 11 (published content), 05 (storefront read API), 20 (schema), 33 (moderation log).
0) Goal (one sentence)
Section titled “0) Goal (one sentence)”Support optional multi-product merchandising by allowing one testimonial submission to link to additional products while preserving a single canonical primary product binding.
1) Blueprint intent recap
Section titled “1) Blueprint intent recap”Blueprint states:
TestimonialProductLinkis an optional extension.- Primary product linkage should come from
TestimonialSubmission.shopifyProductId.
That means:
- multi-link is additive,
- never replace the need for primary binding.
2) Model contract (§5.9)
Section titled “2) Model contract (§5.9)”Required fields:
idshopIdsubmissionIdshopifyProductIdcreatedAt
Unique constraint:
@@unique([submissionId, shopifyProductId])
Recommended indexes:
@@index([shopId, shopifyProductId])@@index([submissionId])
3) Scope boundaries
Section titled “3) Scope boundaries”In scope
Section titled “In scope”- Persist secondary product links.
- Expose/edit links from submission detail screen.
- Use links where relevant in publication and recommendation contexts.
Out of scope (v1)
Section titled “Out of scope (v1)”- Auto-generating links via AI similarity.
- Mass-linking from bulk actions.
- Link weighting/scoring.
4) Primary vs secondary product rules
Section titled “4) Primary vs secondary product rules”4.1 Primary product (always required)
Section titled “4.1 Primary product (always required)”- Stored in
TestimonialSubmission.shopifyProductId. - Derived from original request token by default.
4.2 Secondary products (optional)
Section titled “4.2 Secondary products (optional)”- Stored in
TestimonialProductLink. - Must not duplicate primary product.
4.3 Invariants
Section titled “4.3 Invariants”- Every submission has exactly one primary product.
- Secondary links are unique per submission.
- Secondary links can be empty.
5) Admin UX behavior (Screen 6 integration)
Section titled “5) Admin UX behavior (Screen 6 integration)”In submission detail (10):
- Product picker supports multi-select.
- UI separates:
- Primary product (single-select/radio)
- Additional linked products (multi-select chips)
Save flow:
- update primary product on submission if changed
- replace secondary links set in
TestimonialProductLink
Use transaction to keep both consistent.
6) Write contract
Section titled “6) Write contract”Suggested server action intent:
intent=save_merchandising_products
Payload:
submissionIdprimaryShopifyProductIdsecondaryShopifyProductIds[]
Validation:
- all products belong to same shop catalog
- secondary list excludes primary
- dedupe secondary IDs before write
Transaction:
- update submission primary id
- delete old link rows for submission
- insert new secondary link rows
- append moderation log action (
featureoredit_products, if you add custom action taxonomy)
7) Storefront/API behavior impact
Section titled “7) Storefront/API behavior impact”7.1 PDP placement
Section titled “7.1 PDP placement”For strict PDP widget query:
- match primary product only by default (recommended for clarity).
Optional expansion mode (future):
- include testimonials where current product appears in
TestimonialProductLink.
If enabled, document clearly in settings to avoid merchant confusion.
7.2 Home/collection
Section titled “7.2 Home/collection”Secondary links are useful for:
- attribution in cards (“Also tagged in …”)
- product recommendation overlays
Not required for base home carousel behavior.
8) Analytics impact
Section titled “8) Analytics impact”If secondary links are enabled:
- product coverage metrics may overcount if you naively count both primary and secondary.
Recommendation:
- default analytics use primary product coverage.
- optional advanced metric can include secondary-linked coverage separately.
9) Compliance and lifecycle
Section titled “9) Compliance and lifecycle”- On submission delete/redact:
- cascade delete linked
TestimonialProductLinkrows.
- cascade delete linked
- No PII in this table; safe for broad internal use.
Keep tenant scoping via shopId to simplify queries and deletions.
10) Acceptance criteria
Section titled “10) Acceptance criteria”- Submission can save primary + multiple secondary products in one action.
- Duplicate secondary products are blocked by validation and DB unique constraint.
- Primary product cannot appear in secondary links.
- Secondary links persist and reload correctly in detail screen.
- Cascades clean link rows when submission is removed.
11) Suggested implementation order (for Cursor)
Section titled “11) Suggested implementation order (for Cursor)”- Add Prisma model and migration (
20alignment). - Add product-link read/write helpers in server layer.
- Update submission detail UI to manage primary + secondary links.
- Add transactional action handler and validation.
- Decide/storefront query policy for secondary links and document in
05/11.
12) References
Section titled “12) References”02-Implementation-Blueprint.md— §5.910-submission-detail-screen-6.md11-published-content-screen-7.md05-storefront-widgets-and-read-api.md20-database-design-and-migrations-blueprint-section-5.md
13) Note on numbering
Section titled “13) Note on numbering”This folder already includes 05 through 34 plans. This file is 35-....