mhinspeya/categorycontent-hyva

A Magento 2 extension for strategically placing advertising content within category grids with pixel-perfect positioning. Supports device-specific (mobile/desktop) ads, multi-store environments, and granular control over row, column, and page placement.

Maintainers

Package info

git.modehaus.de/hyvae/advertising-content

Homepage

Type:magento2-module

pkg:composer/mhinspeya/categorycontent-hyva

Transparency log

Statistics

Installs: 15

Dependents: 0

Suggesters: 0

1.0.3 2026-08-04 10:34 UTC

This package is not auto-updated.

Last update: 2026-08-04 10:35:09 UTC


README

License

Magento 2 / Hyvä extension that places advertising / promotional cards inside the category product grid with exact page, row, and column control. Supports separate desktop and mobile creatives, multi-store targeting, scheduling, live enable/disable via AJAX (FPC / LiteMage friendly), URL validation, ACL, and sample data.

Module: MHinspeya_CategoryContent
Composer: mhinspeya/categorycontent-hyva
Requires: mhinspeya/backend-mod, Hyvä theme (frontend list override)

Features

Placement & targeting

  • Insert promo cards into the category product grid by page, row, and column
  • Separate placement settings for Desktop and Mobile (tablet uses mobile creatives)
  • Assign one or more categories and store views per record
  • Optional title (also used as image alt on the frontend)

Images & links

  • Desktop and mobile image upload (JPG/JPEG/PNG, max 15 MB)
  • Recommended desktop size: 265×664 px; mobile sample size: 320×640 px
  • Redirect URL per device with Magento validate-url (client) and server-side http/https checks
  • Open link in new tab toggle (target="_blank" + rel="noopener")

Scheduling

  • Optional Start Date & Time / End Date & Time
  • Calendar picker only (keyboard typing disabled)
  • Times use Magento store timezone; values are stored in UTC
  • Inactive / out-of-schedule promos are not injected on the frontend

Live enable / disable (cache-friendly)

  • Global switch: Stores → Configuration → MHINSPEYA.DE → Advertising Content → Enable
  • Category list loads products from HTML; promo cards are injected via AJAX
    (categorycontent/ajax/config) with no-store / no-cache headers so FPC / LiteMage can keep the product list cached while promo state stays live
  • The AJAX call always runs on category pages with products (by design). That is how enable/disable and schedules update without flushing FPC. When disabled, the response is a small JSON (enabled: false, empty images) — ads are not shown, and category HTML TTFB is unchanged

Admin UX

  • Full CRUD UI listing + form
  • View on Storefront action opens the first assigned category (correct store + optional ?p= page) in a new tab
  • Mass actions: Enable, Disable, Delete
  • Inline edit for selected fields
  • Slot conflict protection: saving is blocked if another enabled record uses the same desktop/mobile page+row+column with overlapping store views and an overlapping schedule (different stores are allowed)
  • Frontend fallback: if two active promos still claim the same slot, the newest record (highest ID) wins

ACL & API

  • Role resources under Inspeya → Advertising Content:
    • View / Save / Delete
    • Advertising Content Configuration
  • REST routes under /V1/mhinspeya-categorycontent/categorycontent (view / save / delete ACL aligned)

Sample data

  • Data patch installs 5 sample records from CSV + fixture images
    (Setup/Patch/Data/InstallSampleCategoryContent.php)

Localization

  • German translations: i18n/de_DE.csv

Installation

In production mode, prefer setup:upgrade --keep-generated when you do not need a full regenerate.

Option 1: Composer (recommended)

composer require mhinspeya/categorycontent-hyva

php bin/magento module:enable MHinspeya_CategoryContent
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento setup:static-content:deploy -f
php bin/magento cache:flush

Option 2: Manual (ZIP / app/code)

  1. Copy the package to:

    app/code/MHinspeya/CategoryContent

  2. Run:

php bin/magento module:enable MHinspeya_CategoryContent
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento setup:static-content:deploy -f
php bin/magento cache:flush

setup:upgrade applies schema changes and the sample data patch (CSV + images) on first install.

Re-install sample data only

If you truncated the content table and need samples again:

TRUNCATE TABLE mhinspeya_categorycontent_categorycontent;
DELETE FROM patch_list
WHERE patch_name = 'MHinspeya\\CategoryContent\\Setup\\Patch\\Data\\InstallSampleCategoryContent';
php bin/magento setup:upgrade
php bin/magento cache:flush

Do not delete the patch PHP class under Setup/Patch/Data/ — Magento needs it to run.

Configuration

Global enable

Path: Stores → Configuration → MHINSPEYA.DEAdvertising Content → General → Enable

Config path: category_content/general/activate

Also available from the admin menu:
Inspeya → Advertising Content → Configuration

Manage advertising content

Menu: Inspeya → Advertising Content → Manage Advertising Content

Create/edit records with:

AreaFields
GeneralStores, Enable, Title, Categories, Start/End Date & Time, Open in New Tab
DesktopPage, Row, Column, Image, URL
MobilePage, Row, Column, Image, URL

Admin roles (ACL)

System → Permissions → User Roles → Role Resources:

  • Advertising Content (parent)
    • View Advertising Content
    • Save Advertising Content
    • Delete Advertising Content
    • Advertising Content Configuration

Assign these after install/upgrade if you use custom roles (not required for Administrators).

Frontend behaviour

  1. Category product list renders the product grid (Hyvä template override).
  2. JS calls GET /categorycontent/ajax/config?category_id={id} (cache: 'no-store').
  3. If globally enabled, matching active promos for the current store/category/schedule are returned.
  4. Cards are inserted at the configured row/column for the current listing page and device breakpoint:
    • Desktop: width > 1024 (4 columns assumed)
    • Tablet: 768–1024 (uses mobile creatives, 2 columns)
    • Mobile: ≤ 767 (2 columns)

Recommended image sizes

DeviceSuggested size
Desktop card265 × 664 px
Mobile card320 × 640 px (or same portrait ratio)

Allowed types: JPG, JPEG, PNG (max 15 MB).

Media folders:

  • Desktop: pub/media/wysiwyg/categorycard/
  • Mobile: pub/media/wysiwyg/categorycardmobile/

Sample data (CSV)

Fixture path:

Setup/Patch/Data/fixtures/category_content.csv
Images: Setup/Patch/Data/fixtures/images/desktop|mobile/

CSV supports:

  • {{base_url}} in redirect URLs
  • Relative dates: now, +1 year, etc. (resolved in store timezone, stored as UTC)

Default samples target Luma demo categories (Yoga, Bags, Fitness, Watches, Tops).

Technical notes

  • Frontend route frontName: categorycontent
  • Admin route: mhinspeya_categorycontent
  • DB table: mhinspeya_categorycontent_categorycontent
  • No ObjectManager in module controllers/helpers (constructor DI)
  • Schedule comparison and AJAX “now” use Magento store timezone, not browser time

Compatibility

  • Magento 2.4.x
  • Hyvä Theme (category product list template)
  • Multi-store
  • Designed to work with full-page cache / LiteMage for product lists while promo config stays uncached via AJAX

Support

QA / Test cases

See TESTCASES.md for full manual/automation test cases (install, config, admin, URLs, images, schedule, placement, conflicts, AJAX/cache, ACL, sample data).