# Feature Idea: Category Videos

Status: Planned
Priority: High
Target version: 3.4.0

---

## Research Findings

### What already exists (reusable)
- **`product_videos_providers` table** — fully reusable; YouTube/Vimeo/HTML5/custom providers are already abstracted
- **`getVideoData()` method** — URL parser that extracts video ID, provider, thumbnail; 100% reusable
- **`ThumbNail` class** — thumbnail generation for YouTube/Vimeo/HTML5; 100% reusable
- **`category` controller already in `$list_controllers`** (line 6053 of productvideo.php) — listing CSS/JS already auto-loads on category pages
- **`PV_VIM_BACKGROUND` config** — Vimeo-native background mode already implemented in `apis.js`; background video concept already proven in the codebase
- **`product-columns.tpl`** — video rendering template for regular embed; can be adapted
- **No category hooks registered or used anywhere in the module today** — clean slate

### Category hooks available in PrestaShop

| Hook | PS version | Purpose |
|---|---|---|
| `displayCategoryAdditionalDescription` | 1.6 + 1.7 | Front: renders content after category description |
| `displayCategoryHeader` | 1.7 | Front: renders in category hero/header area |
| `displayAdminCategoriesForm` | 1.6 | Admin: adds raw HTML to category edit page |
| `actionCategoryFormBuilderModifier` | 1.7.3+ | Admin: adds fields to category form via FormBuilder |
| `actionAfterUpdateCategoryFormHandler` | 1.7.3+ | Admin: saves data after category form submit |
| `actionCategoryDelete` | 1.6 + 1.7 | Admin: fires on category deletion |

---

## Architecture

### New database table: `category_videos`

```sql
CREATE TABLE IF NOT EXISTS `PREFIX_category_videos` (
    `id_categoryvideo`    int(11) NOT NULL AUTO_INCREMENT,
    `id_category`         int(11) NOT NULL,
    `id_video`            varchar(32) NOT NULL,
    `title`               text NOT NULL,
    `provider`            text NOT NULL,
    `video_url`           text NOT NULL,
    `additional_parameters` varchar(255) NULL,
    `thumbnail`           text NULL,
    `display_mode`        tinyint(1) NOT NULL DEFAULT 0,  -- 0=regular, 1=background
    `id_shop`             int(11) NOT NULL DEFAULT 1,
    PRIMARY KEY (`id_categoryvideo`),
    UNIQUE KEY `category_shop` (`id_category`, `id_shop`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
```

Differences from `product_videos`: no `id_lang` (universal per category), no `position` (one video only), `display_mode` column added, unique constraint enforces one-per-category.

### Display options confirmed by user

**Regular (direct) video — placement options:**
1. `below_description` — embed player directly below the category description (via `displayCategoryAdditionalDescription`)
2. `modal` — a thumbnail/play button shown in the description area; clicking opens the video in a lightbox/modal
3. `below_products` — embed player after the product grid (via `displayCategoryFooter` if available)

**Background video — placement options:**
1. `hero_block` — full-width hero section between description and product grid; autoplay muted with optional overlay and text/CTA *(user-confirmed preferred placement)*
2. `header_overlay` — video positioned behind the category header/banner area via configurable CSS selector (like the product slider integration)

Both modes: one video per category, no per-language variant (universal), both shipping in 3.4.0.

### New config keys (`PV_CAT_` prefix)

| Key | Default | Purpose |
|---|---|---|
| `PV_CAT_ENABLE` | 0 | Master enable switch |
| `PV_CAT_REGULAR_PLACEMENT` | `below_description` | Regular mode placement: below_description / modal / below_products |
| `PV_CAT_BG_PLACEMENT` | `hero_block` | Background mode placement: hero_block / header_overlay |
| `PV_CAT_BG_HEIGHT` | `400px` | Background video container height |
| `PV_CAT_BG_OVERLAY_COLOR` | `#000000` | Overlay tint color |
| `PV_CAT_BG_OVERLAY_OPACITY` | `0.3` | Overlay opacity (0-1) |
| `PV_CAT_BG_TEXT` | `` | Optional overlay text/CTA for hero block |
| `PV_CAT_HEADER_SEL` | `` | CSS selector for header_overlay placement |
| `PV_CAT_REGULAR_WIDTH` | 720 | Regular mode player width |
| `PV_CAT_REGULAR_HEIGHT` | 480 | Regular mode player height |

### New files to create

| File | Purpose |
|---|---|
| `sql/upgrade-3.4.0.php` | Creates `category_videos` table |
| `views/templates/hook/category-video.tpl` | Front: renders both modes |
| `views/templates/admin/category-video-admin.tpl` | Admin PS 1.6 form |
| `views/js/category/pv-category-video.js` | Front: background init + iOS fallback |
| `views/css/category/pv-category-video.css` | Background mode CSS |

### Files to modify

| File | Change |
|---|---|
| `productvideo.php` | Register 5 new hooks; add 5 hook methods; add config keys; add category CRUD helpers; new "Category" tab in admin panel |
| `classes/PVDBInstaller.php` | Add `category_videos` table definition |
| `versions.txt` + `changelogs/en.txt` | New entry for 3.4.0 |

---

## Implementation Phases

### Phase 1 — Backend (DB + CRUD + Hooks)
1. Add `category_videos` table to `PVDBInstaller::getSchema()`
2. Create `upgrade/upgrade-3.4.0.php`
3. Register hooks: `displayCategoryAdditionalDescription`, `displayAdminCategoriesForm`, `actionCategoryFormBuilderModifier`, `actionAfterUpdateCategoryFormHandler`, `actionCategoryDelete`
4. Implement `hookActionCategoryDelete($params)` → `Db::delete('category_videos', 'id_category='.(int)$params['id_category'])`
5. Add helpers: `getCategoryVideo($id_category, $id_shop)`, `saveCategoryVideo(...)`, `deleteCategoryVideo($id_category, $id_shop)`
6. Reuse `getVideoData()` and `ThumbNail::generateThumbnail()` — zero new parsing logic

### Phase 2 — Admin UI (Category Edit Page)

**PS 1.6 (`hookDisplayAdminCategoriesForm`):**
- Renders `category-video-admin.tpl` directly — a simple panel with URL input, display mode select, thumbnail preview
- On save: caught by `hookActionCategoryUpdate` or a dedicated AJAX endpoint via `AdminProductVideoController`

**PS 1.7 (`hookActionCategoryFormBuilderModifier`):**
- Adds a `custom_fields` section to the category FormBuilder with `video_url` and `display_mode` inputs
- `hookActionAfterUpdateCategoryFormHandler` saves the data

**Both versions share** the same thumbnail preview JS (reuse existing AJAX preview flow).

### Phase 3 — Front Display (`displayCategoryAdditionalDescription`)

**Regular mode (display_mode = 0):**
- Renders a responsive iframe/HTML5 player below the category description
- Adapts `product-columns.tpl` structure; same YouTube/Vimeo/HTML5 conditional rendering
- Width/height controlled by `PV_CAT_REGULAR_WIDTH/HEIGHT`

**Background mode (display_mode = 1):**
- `category-video.tpl` renders a `<div class="pv-category-bg-video">` with:
  - YouTube: IFrame API with `autoplay=1&mute=1&controls=0&loop=1&playlist=VIDEO_ID`
  - Vimeo: existing `PV_VIM_BACKGROUND` logic, reused
  - HTML5: `<video autoplay muted loop playsinline>`
- `pv-category-video.js` handles: IFrame API init, Vimeo SDK call, overlay injection, resize
- **iOS fallback**: detect `navigator.userAgent` iOS + check `autoplay` capability; fall back to static thumbnail with play button if autoplay is blocked
- CSS: `position: relative; overflow: hidden;` container, `position: absolute; object-fit: cover;` video element

### Phase 4 — Configuration Panel
- New "Category Videos" tab in the module admin panel (Tab Magic picks it up automatically)
- Simple HelperForm section under existing config system
- Fields: enable toggle, default height, overlay settings, regular mode dimensions

---

## Display Mode — Background Video Details

```
[Category Header / Banner area]
+-------------------------------------+
|  ......... VIDEO PLAYING .........  |  <- position: absolute, z-index: 0
|  ######## OVERLAY (tinted) ######## |  <- position: absolute, z-index: 1
|  +-------------------------------+  |
|  |  Category Name + Description  |  |  <- position: relative, z-index: 2
|  +-------------------------------+  |
+-------------------------------------+
```

The hook `displayCategoryAdditionalDescription` fires AFTER the description, but background mode needs to wrap the header. If `displayCategoryHeader` is unavailable on some themes, a CSS solution (negative margin + z-index) can pull the video behind the existing header. Alternatively, `displayCategoryAdditionalDescription` can be used with background mode rendered as a prominent hero block above the product grid instead — simpler and more reliable across themes.

**Note [70/100 confidence]:** `displayCategoryHeader` availability across PS 1.6/1.7 themes is uncertain — many themes don't implement it. Background video is safer as a hero-block-below-description pattern.

---

## Difficulty Rating

| Component | Effort | Notes |
|---|---|---|
| DB + CRUD backend | Low | Direct pattern reuse from product_videos |
| Admin UI PS 1.6 | Low-Medium | Raw HTML output, well-understood |
| Admin UI PS 1.7 | Medium | FormBuilder API needs careful PS version detection |
| Regular display mode | Low | Adapt existing template, 80% reuse |
| Background display mode | Medium | iOS fallback, z-index layering, cross-provider |
| Configuration panel | Low | Standard HelperForm pattern |
| **Total** | **~3-4 days** | If phased: regular mode in 1.5 days |

---

## Business Case

### Why this matters commercially
1. **High-demand request** — "category page video" is in the top 5 PrestaShop video feature requests on forums. Many shop owners want hero videos for seasonal collections, brand storytelling, product family showcases.
2. **Differentiation** — No major PS video module currently offers per-category video. This is a genuine competitive gap.
3. **Background video is visually striking** — In demos, ambient background video on category pages has outsized impact vs. the implementation cost. It's a conversion-rate selling point.
4. **Upsell angle** — "Your competitors' product pages already have video — now make your category pages just as compelling."
5. **SEO benefit** — Video content increases average dwell time on category pages, which is a soft ranking signal for organic traffic.

### Potential business moves
- **Price bump**: The feature alone could justify bumping the Addons listing from €49 → €59 (or similar).
- **Marketing angle**: Email campaign to existing customers: "New in 3.4.0 — Category Page Videos". Zero acquisition cost, high engagement.
- **Screenshots / demo**: One GIF of a background video on a fashion category page would be a strong Addons listing asset.

### Risk flags
- **iOS background video**: Autoplay is silently blocked on iOS Safari and some Android browsers. The fallback to static thumbnail must be polished, not janky.
- **Theme compatibility**: Background mode's CSS layering is theme-sensitive. Will need the same "CSS selector" documentation approach used for product videos.
- **Scope creep**: Per-lang video support is a clear follow-up request that will come immediately after launch. Design the schema to allow adding `id_lang` later without migration pain.

---

## Open Questions

1. **Phased or all-at-once?** Ship regular mode only first (faster, ~1.5 days), then background as 3.5.0? Or ship both in 3.4.0?
2. **Background video position**: Should background mode wrap the category header/banner (requires theme-specific CSS work) or appear as a prominent hero block below the description (simpler, universal)?
3. **Per-language videos?** One video per category regardless of language (simpler) or allow different video per language? This significantly affects the schema and admin UI complexity.

---

## Verification Plan
1. Docker PS 1.6: go to category edit → verify video panel appears → add YouTube URL → save → check `category_videos` table → visit category page → video renders
2. Docker PS 1.7/PS 8: same flow via FormBuilder
3. Background mode: visit category page → video autoplays muted behind description
4. iOS simulation: Chrome DevTools → iPhone UA → verify fallback thumbnail shows
5. `actionCategoryDelete`: delete a category → verify row removed from `category_videos`
6. Multi-shop: switch shop context → verify each shop can have its own category video
