Collection Landing Pages ======================== Scope ----- Collections are used primarily under **Kitchen Cabinets** today. The same model supports other top categories later (e.g. Bathroom Vanities, Doors, Mouldings) — set ``category_l1`` on each collection record and keep path slugs under that hub (``bathroom-vanities/{collection-name}``, etc.). Category Shape -------------- Customer-facing kitchen cabinet paths should prioritize shopping intent: - Kitchen Cabinets - Kitchen Cabinets / Base Cabinets - Kitchen Cabinets / Wall Cabinets - Kitchen Cabinets / Panels and Fillers - Kitchen Cabinets / Mouldings - Kitchen Cabinets / Accessories - Kitchen Cabinets / Anna Stone Gray - Kitchen Cabinets / Anna Snow White - Kitchen Cabinets / Anna Caramel Harvest Brand remains product metadata and a filter/facet, not the default middle category level: - brand = Port & Bell - Optional brand page: /brands/port-and-bell Avoid customer-facing paths like Kitchen Cabinets / Port & Bell / Anna Stone Gray unless a brand-first landing page is explicitly needed. Hierarchy (current vs future) ----------------------------- **Current (Kitchen Cabinets focus):** - Top hub: ``Kitchen Cabinets`` - Type subcategories: ``Kitchen Cabinets / Base Cabinets``, ``Wall Cabinets``, etc. - Collections: **direct children of the hub** — ``Kitchen Cabinets / Anna Stone Gray`` **Future (optional nesting):** - Collection under a type subcategory, e.g. ``Kitchen Cabinets / Base Cabinets / Anna Stone Gray`` - Controlled by ``collection_landing_page.parent_path_slug`` (defaults to the hub slug) **Downstream channel behavior:** - **Magento** — hierarchical categories; parent comes from ``parent_path_slug`` / hub. Breadcrumb follows master path segments. - **Shopify** — flat manual collections only (no category tree). Master path slug is kept for linking, but the remote collection **title/handle** uses the collection name only (e.g. ``Anna Stone Gray``, not ``Kitchen Cabinets / Anna Stone Gray``). - Channel placement DTO: ``db/collection_channel_placement.py`` and ``GET /api/channel/collections/export?channel=...`` → ``channel.placement``. Other verticals (Bathroom Vanities, Doors, Mouldings) use the same style-prefix pattern; SKU prefix maps may differ per category as master data grows. Page Types ---------- Top Category Example: Kitchen Cabinets - Category hero - Trust/benefit strip - Collection grid - Subcategory navigation - Filtered product grid Subcategory Example: Kitchen Cabinets / Base Cabinets - Category hero - Collection grid filtered to collections with matching SKUs - Product grid filtered to that subcategory Collection Example: Kitchen Cabinets / Anna Stone Gray - Collection hero/gallery - Brand and collection title - Short description - Badges and feature bullets - Starting price - Info sheet PDF - CTA rows - Matching collections - Description/specifications/materials/assembly accordion - Subcategory navigation - Product grid filtered to the collection Source Of Truth --------------- Collection metadata owns presentation fields: - title - brand - collection name - hero images - thumbnail image - PDF URL - short and long description - badges - feature bullets - CTA rows - matching collection slugs - specifications - materials - assembly instructions SKU membership is derived — never duplicated as a static list on the collection row. Three discovery sources are merged; manual overrides win last: 1. **Master data** — ``master_product.collection`` (+ ``category_l1`` filter) 2. **SKU prefix** — leading master style code on the SKU (e.g. ``ASW`` → Anna Snow White) configured per collection in ``collection_landing_page.sku_prefixes`` 3. **Manual assignments** — ``collection_sku_override`` rows: - ``include`` — force SKU into collection even when auto rules miss it - ``exclude`` — remove SKU even when auto rules match Apply/sync writes ``product_listing_path_assignment`` with ``match_source`` set to ``master_collection``, ``sku_prefix``, or ``manual_include``. SKUs that no longer resolve (including ``manual_exclude``) are **deactivated** on apply for that path. Related catalog fields (subcategory grids, not collection membership): - master_product_attribute_value.cabinet_type_sub_category_1 - product_listing_path_assignment (materialized target for channel PLPs) Default SKU prefix map (master style code → collection display name) lives in ``db/collection_sku_mapping.py`` (from Tribeca ``STYLE_COLLECTION_TO_CODE``). Prefix rules are independent of channel SKU prefix rules (``HD-SNW`` etc.). Channel export (Magento / Shopify — presentation push): - ``GET /api/channel/collections/export?channel=magento|shopify`` - Returns landing metadata + resolved SKU list + channel taxonomy ids + placement DTO Channel bootstrap (create remote field definitions once per store): - ``POST /api/channel/collections/bootstrap?channel=magento|shopify`` - Shopify: ``COLLECTION`` metafield definitions under namespace ``custom`` - Magento: discover existing category custom attributes prefixed ``hs_`` on ``catalog_category`` (Magento REST cannot create category attributes — use ``GET /api/channel/collections/magento-attribute-patch`` and deploy the PHP data patch, then re-run bootstrap) Channel push (write landing content to mapped remote categories/collections): - ``POST /api/channel/collections/push`` - Body: ``{ "channel": "magento|shopify", "connection_id": 1, "path_slug": "...", "dry_run": true }`` - Resolves remote id from listing path targets, taxonomy mapping, or channel registry - Shopify sets ``collection.metafields.custom.*`` + optional ``descriptionHtml`` - Magento sets category ``custom_attributes`` via ``PUT /V1/categories/{id}`` Field map (canonical key → both channels): - page_type, brand, subtitle, short_description - thumbnail_image_url, pdf_url, starting_price - hero_images, badges, feature_bullets, cta_rows, matching_collection_slugs, sku_prefixes (JSON) - description_html, specifications_html, materials_html, assembly_html Naming Normalization -------------------- Use canonical collection names in API and UI: - Anna Stone Grey -> Anna Stone Gray - Kitchen Cabinet -> Kitchen Cabinets - Panels & Fillers -> Panels and Fillers Display labels may preserve marketing copy, but keys/slugs should use the canonical names. Master Collection Registry (catalog intent alignment) ----------------------------------------------------- Canonical collection series live in ``master_collection_registry`` (code, name, path_slug, brand_id, family_id, aliases JSONB). Linking: - ``master_product.collection_registry_id`` — preferred SKU membership match (before text collection / prefix fallbacks) - ``collection_landing_page.collection_registry_id`` — durable link when marketing names/slugs change; ``path_slug`` remains the public URL key - Bridge: ``db/collection_taxonomy_bridge.link_collection_registry_to_landing`` syncs landing FK from shared ``path_slug`` - Diagnostics: ``GET /api/dashboard/collections/{path_slug}/channel-targets`` includes ``registry`` consistency payload APIs: - ``GET/POST /api/master-taxonomy/collections`` — registry CRUD - ``POST /api/dashboard/collections/{path_slug}/link-registry`` — align landing page FK - ``POST /api/master-taxonomy/backfill`` — seed registries from distinct master_product text fields