feat: scheduling, A/B testing, repo metadata update #60
@@ -90,6 +90,25 @@ MOD_MOKOJOOMHERO_PARALLAX_DESC="Background moves at a slower rate than page cont
|
||||
MOD_MOKOJOOMHERO_PARALLAX_SPEED_LABEL="Parallax Speed"
|
||||
MOD_MOKOJOOMHERO_PARALLAX_SPEED_DESC="How much the background moves relative to scroll (0.1 = subtle, 0.9 = dramatic)."
|
||||
|
||||
; A/B testing
|
||||
MOD_MOKOJOOMHERO_FIELDSET_AB="A/B Testing"
|
||||
MOD_MOKOJOOMHERO_AB_ENABLED_LABEL="Enable A/B Testing"
|
||||
MOD_MOKOJOOMHERO_AB_ENABLED_DESC="Randomly show different content variations to visitors. Assignment is sticky per session."
|
||||
MOD_MOKOJOOMHERO_AB_VARIATIONS_LABEL="Variations"
|
||||
MOD_MOKOJOOMHERO_AB_VARIATIONS_DESC="Define content variations with relative weights. Higher weight = higher chance of being shown."
|
||||
MOD_MOKOJOOMHERO_AB_VAR_LABEL="Label"
|
||||
MOD_MOKOJOOMHERO_AB_VAR_CONTENT="Content"
|
||||
MOD_MOKOJOOMHERO_AB_VAR_WEIGHT="Weight"
|
||||
|
||||
; Scheduling
|
||||
MOD_MOKOJOOMHERO_FIELDSET_SCHEDULING="Scheduling"
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_ENABLED_LABEL="Enable Scheduling"
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_ENABLED_DESC="Only display the hero during a specific date/time range. Uses the site timezone."
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_START_LABEL="Start Date/Time"
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_START_DESC="The hero will not display before this date and time. Leave empty for no start restriction."
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_END_LABEL="End Date/Time"
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_END_DESC="The hero will not display after this date and time. Leave empty for no end restriction."
|
||||
|
||||
; Video poster
|
||||
MOD_MOKOJOOMHERO_VIDEO_POSTER_LABEL="Video Poster Image"
|
||||
MOD_MOKOJOOMHERO_VIDEO_POSTER_DESC="Fallback image displayed while the video loads. Prevents a blank hero on slow connections."
|
||||
|
||||
@@ -91,6 +91,25 @@ MOD_MOKOJOOMHERO_PARALLAX_DESC="Background moves at a slower rate than page cont
|
||||
MOD_MOKOJOOMHERO_PARALLAX_SPEED_LABEL="Parallax Speed"
|
||||
MOD_MOKOJOOMHERO_PARALLAX_SPEED_DESC="How much the background moves relative to scroll (0.1 = subtle, 0.9 = dramatic)."
|
||||
|
||||
; A/B testing
|
||||
MOD_MOKOJOOMHERO_FIELDSET_AB="A/B Testing"
|
||||
MOD_MOKOJOOMHERO_AB_ENABLED_LABEL="Enable A/B Testing"
|
||||
MOD_MOKOJOOMHERO_AB_ENABLED_DESC="Randomly show different content variations to visitors."
|
||||
MOD_MOKOJOOMHERO_AB_VARIATIONS_LABEL="Variations"
|
||||
MOD_MOKOJOOMHERO_AB_VARIATIONS_DESC="Define content variations with relative weights."
|
||||
MOD_MOKOJOOMHERO_AB_VAR_LABEL="Label"
|
||||
MOD_MOKOJOOMHERO_AB_VAR_CONTENT="Content"
|
||||
MOD_MOKOJOOMHERO_AB_VAR_WEIGHT="Weight"
|
||||
|
||||
; Scheduling
|
||||
MOD_MOKOJOOMHERO_FIELDSET_SCHEDULING="Scheduling"
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_ENABLED_LABEL="Enable Scheduling"
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_ENABLED_DESC="Only display the hero during a specific date/time range."
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_START_LABEL="Start Date/Time"
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_START_DESC="The hero will not display before this date and time."
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_END_LABEL="End Date/Time"
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_END_DESC="The hero will not display after this date and time."
|
||||
|
||||
; Video poster
|
||||
MOD_MOKOJOOMHERO_VIDEO_POSTER_LABEL="Video Poster Image"
|
||||
MOD_MOKOJOOMHERO_VIDEO_POSTER_DESC="Fallback image displayed while the video loads."
|
||||
|
||||
@@ -107,6 +107,25 @@ MOD_MOKOJOOMHERO_PARALLAX_DESC="Background moves at a slower rate than page cont
|
||||
MOD_MOKOJOOMHERO_PARALLAX_SPEED_LABEL="Parallax Speed"
|
||||
MOD_MOKOJOOMHERO_PARALLAX_SPEED_DESC="How much the background moves relative to scroll (0.1 = subtle, 0.9 = dramatic)."
|
||||
|
||||
; A/B testing
|
||||
MOD_MOKOJOOMHERO_FIELDSET_AB="A/B Testing"
|
||||
MOD_MOKOJOOMHERO_AB_ENABLED_LABEL="Enable A/B Testing"
|
||||
MOD_MOKOJOOMHERO_AB_ENABLED_DESC="Randomly show different content variations to visitors. Assignment is sticky per session."
|
||||
MOD_MOKOJOOMHERO_AB_VARIATIONS_LABEL="Variations"
|
||||
MOD_MOKOJOOMHERO_AB_VARIATIONS_DESC="Define content variations with relative weights. Higher weight = higher chance of being shown."
|
||||
MOD_MOKOJOOMHERO_AB_VAR_LABEL="Label"
|
||||
MOD_MOKOJOOMHERO_AB_VAR_CONTENT="Content"
|
||||
MOD_MOKOJOOMHERO_AB_VAR_WEIGHT="Weight"
|
||||
|
||||
; Scheduling
|
||||
MOD_MOKOJOOMHERO_FIELDSET_SCHEDULING="Scheduling"
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_ENABLED_LABEL="Enable Scheduling"
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_ENABLED_DESC="Only display the hero during a specific date/time range. Uses the site timezone."
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_START_LABEL="Start Date/Time"
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_START_DESC="The hero will not display before this date and time. Leave empty for no start restriction."
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_END_LABEL="End Date/Time"
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_END_DESC="The hero will not display after this date and time. Leave empty for no end restriction."
|
||||
|
||||
; Video poster
|
||||
MOD_MOKOJOOMHERO_VIDEO_POSTER_LABEL="Video Poster Image"
|
||||
MOD_MOKOJOOMHERO_VIDEO_POSTER_DESC="Fallback image displayed while the video loads. Prevents a blank hero on slow connections."
|
||||
|
||||
@@ -91,6 +91,25 @@ MOD_MOKOJOOMHERO_PARALLAX_DESC="Background moves at a slower rate than page cont
|
||||
MOD_MOKOJOOMHERO_PARALLAX_SPEED_LABEL="Parallax Speed"
|
||||
MOD_MOKOJOOMHERO_PARALLAX_SPEED_DESC="How much the background moves relative to scroll (0.1 = subtle, 0.9 = dramatic)."
|
||||
|
||||
; A/B testing
|
||||
MOD_MOKOJOOMHERO_FIELDSET_AB="A/B Testing"
|
||||
MOD_MOKOJOOMHERO_AB_ENABLED_LABEL="Enable A/B Testing"
|
||||
MOD_MOKOJOOMHERO_AB_ENABLED_DESC="Randomly show different content variations to visitors."
|
||||
MOD_MOKOJOOMHERO_AB_VARIATIONS_LABEL="Variations"
|
||||
MOD_MOKOJOOMHERO_AB_VARIATIONS_DESC="Define content variations with relative weights."
|
||||
MOD_MOKOJOOMHERO_AB_VAR_LABEL="Label"
|
||||
MOD_MOKOJOOMHERO_AB_VAR_CONTENT="Content"
|
||||
MOD_MOKOJOOMHERO_AB_VAR_WEIGHT="Weight"
|
||||
|
||||
; Scheduling
|
||||
MOD_MOKOJOOMHERO_FIELDSET_SCHEDULING="Scheduling"
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_ENABLED_LABEL="Enable Scheduling"
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_ENABLED_DESC="Only display the hero during a specific date/time range."
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_START_LABEL="Start Date/Time"
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_START_DESC="The hero will not display before this date and time."
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_END_LABEL="End Date/Time"
|
||||
MOD_MOKOJOOMHERO_SCHEDULE_END_DESC="The hero will not display after this date and time."
|
||||
|
||||
; Video poster
|
||||
MOD_MOKOJOOMHERO_VIDEO_POSTER_LABEL="Video Poster Image"
|
||||
MOD_MOKOJOOMHERO_VIDEO_POSTER_DESC="Fallback image displayed while the video loads."
|
||||
|
||||
@@ -23,6 +23,73 @@ $wa = $app->getDocument()->getWebAssetManager();
|
||||
$wa->getRegistry()->addExtensionRegistryFile('mod_mokojoomhero');
|
||||
$wa->usePreset('mod_mokojoomhero');
|
||||
|
||||
// Schedule check — skip rendering if outside the configured date range
|
||||
$scheduleEnabled = (bool) $params->get('scheduleEnabled', 0);
|
||||
|
||||
if ($scheduleEnabled) {
|
||||
$now = new \DateTime('now', new \DateTimeZone($app->get('offset', 'UTC')));
|
||||
$scheduleStart = $params->get('scheduleStart', '');
|
||||
$scheduleEnd = $params->get('scheduleEnd', '');
|
||||
|
||||
if ($scheduleStart) {
|
||||
$start = new \DateTime($scheduleStart, new \DateTimeZone($app->get('offset', 'UTC')));
|
||||
|
||||
if ($now < $start) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ($scheduleEnd) {
|
||||
$end = new \DateTime($scheduleEnd, new \DateTimeZone($app->get('offset', 'UTC')));
|
||||
|
||||
if ($now > $end) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A/B testing — weighted random variation, session-sticky per module instance
|
||||
$abEnabled = (bool) $params->get('abEnabled', 0);
|
||||
$abVariationContent = '';
|
||||
|
||||
if ($abEnabled) {
|
||||
$abVariations = $params->get('abVariations', '');
|
||||
$abData = is_string($abVariations) ? json_decode($abVariations, true) : (array) $abVariations;
|
||||
|
||||
if (is_array($abData) && count($abData) > 0) {
|
||||
$session = \Joomla\CMS\Factory::getSession();
|
||||
$sessionKey = 'mokojoomhero.ab.' . $module->id;
|
||||
$picked = $session->get($sessionKey, null);
|
||||
|
||||
if ($picked === null || !isset($abData[$picked])) {
|
||||
// Weighted random selection
|
||||
$totalWeight = 0;
|
||||
|
||||
foreach ($abData as $v) {
|
||||
$totalWeight += (int) (((array) $v)['weight'] ?? 50);
|
||||
}
|
||||
|
||||
$rand = mt_rand(1, max($totalWeight, 1));
|
||||
$cumulative = 0;
|
||||
$picked = 0;
|
||||
|
||||
foreach ($abData as $i => $v) {
|
||||
$cumulative += (int) (((array) $v)['weight'] ?? 50);
|
||||
|
||||
if ($rand <= $cumulative) {
|
||||
$picked = $i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$session->set($sessionKey, $picked);
|
||||
}
|
||||
|
||||
$variation = (array) ($abData[$picked] ?? []);
|
||||
$abVariationContent = $variation['content'] ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
// Module parameters
|
||||
$heroMode = $params->get('heroMode', 'images');
|
||||
$imageFolder = $params->get('imageFolder', 'images/heroes');
|
||||
@@ -118,6 +185,11 @@ if (!in_array($contentAnimation, $allowedContentAnimations, true)) {
|
||||
$parallaxSpeed = max(0.1, min(0.9, $parallaxSpeed));
|
||||
$gradientAngle = max(0, min(360, $gradientAngle));
|
||||
|
||||
// Apply A/B variation content if active
|
||||
if ($abEnabled && $abVariationContent) {
|
||||
$heroContent = $abVariationContent;
|
||||
}
|
||||
|
||||
// Collect hero images
|
||||
$heroImages = [];
|
||||
|
||||
|
||||
@@ -274,6 +274,89 @@
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
<fieldset name="abtesting"
|
||||
label="MOD_MOKOJOOMHERO_FIELDSET_AB"
|
||||
>
|
||||
<field
|
||||
name="abEnabled"
|
||||
type="radio"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
label="MOD_MOKOJOOMHERO_AB_ENABLED_LABEL"
|
||||
description="MOD_MOKOJOOMHERO_AB_ENABLED_DESC"
|
||||
default="0"
|
||||
>
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
<field
|
||||
name="abVariations"
|
||||
type="subform"
|
||||
label="MOD_MOKOJOOMHERO_AB_VARIATIONS_LABEL"
|
||||
description="MOD_MOKOJOOMHERO_AB_VARIATIONS_DESC"
|
||||
multiple="true"
|
||||
layout="joomla.form.field.subform.repeatable-table"
|
||||
showon="abEnabled:1"
|
||||
max="4"
|
||||
>
|
||||
<form>
|
||||
<field
|
||||
name="label"
|
||||
type="text"
|
||||
label="MOD_MOKOJOOMHERO_AB_VAR_LABEL"
|
||||
filter="string"
|
||||
default="Variation"
|
||||
/>
|
||||
<field
|
||||
name="content"
|
||||
type="textarea"
|
||||
label="MOD_MOKOJOOMHERO_AB_VAR_CONTENT"
|
||||
filter="safehtml"
|
||||
rows="3"
|
||||
/>
|
||||
<field
|
||||
name="weight"
|
||||
type="number"
|
||||
label="MOD_MOKOJOOMHERO_AB_VAR_WEIGHT"
|
||||
default="50"
|
||||
min="1"
|
||||
max="100"
|
||||
/>
|
||||
</form>
|
||||
</field>
|
||||
</fieldset>
|
||||
<fieldset name="scheduling"
|
||||
label="MOD_MOKOJOOMHERO_FIELDSET_SCHEDULING"
|
||||
>
|
||||
<field
|
||||
name="scheduleEnabled"
|
||||
type="radio"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
label="MOD_MOKOJOOMHERO_SCHEDULE_ENABLED_LABEL"
|
||||
description="MOD_MOKOJOOMHERO_SCHEDULE_ENABLED_DESC"
|
||||
default="0"
|
||||
>
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
<field
|
||||
name="scheduleStart"
|
||||
type="calendar"
|
||||
label="MOD_MOKOJOOMHERO_SCHEDULE_START_LABEL"
|
||||
description="MOD_MOKOJOOMHERO_SCHEDULE_START_DESC"
|
||||
format="%Y-%m-%d %H:%M"
|
||||
showtime="true"
|
||||
showon="scheduleEnabled:1"
|
||||
/>
|
||||
<field
|
||||
name="scheduleEnd"
|
||||
type="calendar"
|
||||
label="MOD_MOKOJOOMHERO_SCHEDULE_END_LABEL"
|
||||
description="MOD_MOKOJOOMHERO_SCHEDULE_END_DESC"
|
||||
format="%Y-%m-%d %H:%M"
|
||||
showtime="true"
|
||||
showon="scheduleEnabled:1"
|
||||
/>
|
||||
</fieldset>
|
||||
<fieldset name="content"
|
||||
label="MOD_MOKOJOOMHERO_FIELDSET_CONTENT"
|
||||
>
|
||||
|
||||
@@ -25,6 +25,6 @@
|
||||
</files>
|
||||
|
||||
<updateservers>
|
||||
<server type="extension" name="MokoJoomHero Updates">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/raw/branch/main/updates.xml</server>
|
||||
<server type="extension" name="MokoJoomHero Updates">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/updates.xml</server>
|
||||
</updateservers>
|
||||
</extension>
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
VERSION: 01.08.00
|
||||
VERSION: 01.09.00
|
||||
-->
|
||||
|
||||
<updates>
|
||||
@@ -104,13 +104,13 @@
|
||||
<element>pkg_mokojoomhero</element>
|
||||
<type>package</type>
|
||||
<client>site</client>
|
||||
<version>01.08.00</version>
|
||||
<version>01.09.00</version>
|
||||
<creationDate>2026-06-04</creationDate>
|
||||
<infourl title='Package - MokoJoomHero'>https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/releases/tag/stable</infourl>
|
||||
<downloads>
|
||||
<downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/releases/download/stable/pkg_mokojoomhero-01.08.00.zip</downloadurl>
|
||||
<downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/releases/download/stable/pkg_mokojoomhero-01.09.00.zip</downloadurl>
|
||||
</downloads>
|
||||
<sha256>111fef438f7c30a74019124134ed461e2b92f9db992c45eef7d5f63091a5e0d7</sha256>
|
||||
<sha256>fd8235cee1a6f08a7821ccae95776f2f57e32ccaad5efe64ef8b377dd7ec47df</sha256>
|
||||
<tags><tag>stable</tag></tags>
|
||||
<changelogurl>https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/raw/branch/main/CHANGELOG.md</changelogurl>
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
|
||||
Reference in New Issue
Block a user