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.
Package info
git.modehaus.de/hyvae/advertising-content
Type:magento2-module
pkg:composer/mhinspeya/categorycontent-hyva
Requires
- mhinspeya/backend-mod: ^1.0
Suggests
- mhinspeya/backend-mod: Support Configuration
README
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
alton 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-sidehttp/httpschecks - 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-generatedwhen 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)
Copy the package to:
app/code/MHinspeya/CategoryContentRun:
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.DE → Advertising 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:
| Area | Fields |
|---|---|
| General | Stores, Enable, Title, Categories, Start/End Date & Time, Open in New Tab |
| Desktop | Page, Row, Column, Image, URL |
| Mobile | Page, 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
- Category product list renders the product grid (Hyvä template override).
- JS calls
GET /categorycontent/ajax/config?category_id={id}(cache: 'no-store'). - If globally enabled, matching active promos for the current store/category/schedule are returned.
- 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
| Device | Suggested size |
|---|---|
| Desktop card | 265 × 664 px |
| Mobile card | 320 × 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
- Homepage: https://inspeya.com
- Email: contact@inspeya.com
- License: OSL-3.0
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).