Tag Classification Bulk Update
Overview
Section titled “Overview”Maintain mappings of product tags to categories — creating tag classification records that link tags to product collections. Bulk operations enable operational efficiency. Tag classifications drive analytics, designer assignments, and performance groupings.
Goal: Insert/update many (category_name, tag_name) tag classification mappings at once while maintaining the uniqueness invariant.
API endpoints
Section titled “API endpoints”Tag classification (internal, not yet specced)
Section titled “Tag classification (internal, not yet specced)”| Method | Path | Description |
|---|---|---|
| POST | /api/tag-classifications/bulk | Bulk upsert of tag classification mappings |
| GET | /api/tag-classifications/unclassified | Tags not yet assigned to any category |
Backing catalog endpoints (specced)
Section titled “Backing catalog endpoints (specced)”| Method | Path | Spec | Description |
|---|---|---|---|
| GET | /tags | product.yaml | List all product tags |
| GET | /tags/{tag_id} | product.yaml | Get a single tag |
| POST | /tags | product.yaml | Create a tag |
| PUT | /tags/{tag_id} | product.yaml | Update a tag |
| GET | /categories | product.yaml | List product categories |
Both tag classification endpoints are protected by CF Access. CRUD target: p99 < 200ms for normal payloads.
Schema tables
Section titled “Schema tables”| Table | Module | Role |
|---|---|---|
product_tag | Product | CRUD: tag classification records (UNIQUE(category_name, tag_name)) |
product_category | Product | Read: category definitions |
product | Product | Read: product-to-tag links for coverage analysis |
Infrastructure
Section titled “Infrastructure”| Resource | Type | Purpose |
|---|---|---|
dashboard-api | CF Worker (internal) | Bulk classification endpoint |
| PlanetScale (Hyperdrive) | Managed Postgres | Tag + category data storage |
Main success scenario
Section titled “Main success scenario”- Staff user (Ops/Creative) selects tags and categories in the UI
- UI calls
POST /api/tag-classifications/bulkwith mapping list - API validates input, performs chunked upsert into
product_tag(UNIQUE(category_name, tag_name)) - API optionally enqueues analytics refresh if cached aggregate tables exist
Request:
{ "mode": "upsert", "mappings": [ { "category_name": "Theme", "tag_name": "floral" }, { "category_name": "Theme", "tag_name": "abstract" }, { "category_name": "Device", "tag_name": "iphone-16" } ]}Response:
{ "updated": 120, "created": 34, "errors": []}Exception flows
Section titled “Exception flows”| Issue | Fallback |
|---|---|
| Conflicting category updates | Define “move tag from A to B” semantics (delete prior mapping + insert new) |
| PlanetScale limits | Chunk to < 100k rows per statement |
| Large payloads exceeding CRUD latency | Accept request quickly, process async if payload exceeds threshold |
Acceptance criteria
Section titled “Acceptance criteria”- PASS: After bulk call, tag classifications appear in correct category; unclassified endpoint excludes them
- FAIL: Duplicate classification records; missed inserts; inconsistent uniqueness