# Product Page Pro & SEO Documentation

Installation steps and a complete reference for every setting, with concrete examples — the same level of detail our support uses to help customers.

## Installation

### Requirements

Magento 2.4.x. PHP 8.1–8.5. Works with **Hyvä** (any child theme) and **Luma** (the default Magento theme) — the active theme is detected automatically, no configuration needed. On any other theme the module has no effect (safe no-op, same as being disabled).

### Setup steps

1. Add the credentials you'll receive by email to `auth.json` in your Magento project root:
   ```json
   { "http-basic": { "repo.codingrow.com": { "username": "...", "password": "..." } } }
   ```
2. `composer config repositories.codingrow composer https://repo.codingrow.com`
3. `composer require codingrow/module-ppps`
4. `bin/magento module:enable Codingrow_GalleryColumns`
5. `bin/magento setup:upgrade && bin/magento setup:di:compile`
6. Paste your license key into **Admin → Stores → Configuration → Codingrow Extensions → Product Page Pro & SEO → License → License Key**, save, then `bin/magento cache:flush`.
7. `bin/magento setup:static-content:deploy -f` (if running in `production` mode).

No Tailwind build step or theme configuration is required: every layout-critical rule (grid ratios, sticky positioning, breakpoints) ships as plain CSS inlined in the module's own templates, not as Tailwind utility classes — it works regardless of whether your Hyvä theme's Tailwind build has been configured to scan this module's templates.

### Configuration

**Admin → Stores → Configuration → Codingrow Extensions → Product Page Pro & SEO**

![Product Page Pro & SEO admin configuration: the License field and the four General options with their inline descriptions](screenshot-config.png)

The section has a **License** group (a single field) and a **General** group with five independent toggles. Every toggle defaults to *Yes*, but each takes effect **only when a valid license is present** — without one, the module behaves as if fully disabled (unmodified theme default layout, no error shown to store visitors).

| Field | What it does | Default | Values / notes |
|---|---|---|---|
| **License Key** (License group) | The license key issued for this domain. | empty | Paste the key received after purchase, then `bin/magento cache:flush`. Contact codingrow.com to purchase/renew. |
| **Enable column gallery on desktop** | Shows all product images at once in a 2-column grid instead of one image at a time. | Yes | Desktop ≥ 1024px only; mobile always keeps the theme's native gallery. |
| **Enable sticky buy-box on desktop** | Keeps the price / add-to-cart column in view while the page scrolls. | Yes | Independent of the column gallery, but it is the **prerequisite** for the two options below; it also moves the description directly under the images. |
| **Enable repeated image strip below description** | Shows every product image again, at a fixed size, in a wrapping strip below the description. | Yes | **Requires** the sticky buy-box option above. ~3 per row on desktop, fewer as the screen narrows. |
| **Enable simplified section titles** | Removes the repeated product name next to section titles like "Description". | Yes | **Hyvä only** — no visible effect on Luma (its tabs don't repeat the product name). |
| **Enable product SEO structured data** | Adds a schema.org/Product JSON-LD block (name, image, brand, GTIN, price, availability) so Google can show rich results, and fills a meta description for products that have none. | Yes | Non-visual; applies on desktop and mobile, Hyvä and Luma alike. Independent of the other options. Never overrides a meta description the product already has. |

### Uninstallation

`composer remove codingrow/module-ppps` then `bin/magento setup:upgrade && bin/magento setup:di:compile && bin/magento cache:flush`.

## User guide

### Column gallery

On desktop (1024px and up), every product image is shown at once in a 2-column grid instead of Hyvä's single-image-plus-thumbnail-strip or Luma's Fotorama slider. Mobile is never affected — it always keeps the theme's native gallery behavior (single image, swipeable thumbnail strip below).

![Product page on desktop: the Product Page Pro & SEO 2-column image grid with the sticky buy-box on the right](screenshot-gallery.png)

On Hyvä, this is implemented as an additive block inside the theme's own Alpine.js gallery component, reusing the same image data already loaded for the default gallery — no duplicate JavaScript state.

On Luma, the grid is added alongside the native Fotorama widget (never modified or reinitialized); the two are toggled with plain CSS at the desktop breakpoint.

### Sticky buy-box

**On Hyvä**: both the image column and the price/buy-box column become `position: sticky` — whichever one is naturally shorter (usually the price column, since the image+description column is normally taller) stays pinned in view while the other scrolls past it. The description moves from its default position (below both columns) to directly under the images, inside that same left column.

**On Luma**: only the price/buy-box column stays visually fixed while you scroll, between the header and the end of the product information section — the image and description column always scrolls normally. This is implemented in JavaScript (`transform: translateY()`, recalculated on scroll) rather than CSS `position: sticky`, since sticky positioning was found not to work reliably combined with Luma's native float-based two-column layout. The description is also repositioned to sit directly under the images (Luma's default puts it full-width below both columns).

### Repeated image strip

Requires the sticky buy-box setting. Below the description, every product image is shown again at a fixed size (274×274px), wrapping naturally as the screen narrows — 3 per row on a typical desktop width, fewer per row as it gets narrower, down to 1 per row on mobile. Images only shrink below their fixed size once even a single one no longer fits the available width.

### Simplified section titles

Hyvä's default theme shows "Description / *Product Name*" as the heading above the description tab — redundant once the product name is already prominent elsewhere on a rearranged page. This setting swaps it for a plain "Description" heading. Luma's own tabs never had this repetition, so the setting has no visible effect there.

### Product SEO structured data

Independent of everything above, and not a visual change. When enabled, each product page gets a `schema.org/Product` JSON-LD block describing the product — name, image, brand, GTIN/EAN, and an `Offer` with price, currency, availability and item condition — so search engines can render rich results (price and availability in the SERP, eligibility for Google's free product listings). Every field is best-effort: whatever the product doesn't have (no brand attribute, no EAN, no price) is simply left out, never an error, and the block is emitted the same way on Hyvä and Luma, desktop and mobile.

The same setting also fills a **meta description** for products that don't have one of their own — built from the product's short/long description (or its name as a last resort) — writing it onto the exact page config the store renders into `<head>`. It never touches a product that already has a meta description (for example one set manually or populated by a feed import), so it only ever fills a gap.

### Hyvä and Luma support

The active theme is detected automatically (no configuration needed) by walking up the current theme's parent chain looking for "Hyva" or "Luma" in the theme code. On any theme that isn't a Hyvä or Luma descendant, every plugin in this module is a guaranteed no-op — the page renders exactly as it would without the module installed, never an error.

### License

One license key per Magento domain, entered in **Stores → Configuration → Codingrow Extensions → Product Page Pro & SEO → License → License Key**. The key is validated offline (signature + domain match) with an online revocation check (24h cache, fail-open: if the license server is unreachable, the key stays valid — no dependency on codingrow.com for day-to-day operation). Moving to a new domain requires a new key — contact support with your original purchase details.
