Joomla System Plugin providing complete server-side tracking for e-shops running on Joomla 4/5 + VirtueMart 4.x/5.x. Replaces client-side JS snippets and sends data directly from the server to tracking platforms via their APIs.
| Parameter | Value |
|---|---|
| Plugin ID | plg_system_semakin_sst |
| CMS | Joomla 4.x / 5.x |
| E-commerce | VirtueMart 4.x+ |
| PHP | 8.1+ |
| Current version | 1.0.4 |
Supported platforms: GA4, Google Ads, Sklik.cz, Zbozi.cz, Heureka Verified by Customers, Heureka OCM, Google Customer Reviews.
- Requirements
- Installation
- Enabling the Plugin
- Basic Configuration
- GDPR Consent Setup
- Google Analytics 4
- Google Ads
- Sklik.cz
- Zbozi.cz
- Heureka – Verified by Customers
- Heureka – OCM (Conversion Measurement)
- Google Customer Reviews
- Retry Queue and Task Scheduler
- Logging and Diagnostics
- Uninstallation
- Troubleshooting
1. Requirements
- Joomla 4.x or 5.x
- VirtueMart 4.x or newer
- PHP 8.1 or newer
- MySQL 5.7+ / MariaDB 10.3+
- A GDPR consent component: StoreJExtensions GDPR, Sema Cookie Consent, or CookieYes (or Manual mode)
2. Installation
Obtaining the Package
Download the file plg_system_semakin_sst-1.0.4.zip from SemaHub (semakin.cz).
Installation Steps
- Log in to the Joomla administration panel.
- Navigate to System > Install > Extensions.
- Upload the
plg_system_semakin_sst-1.0.4.zipfile. - After installation, the plugin creates two database tables:
#__semakin_sst_logand#__semakin_sst_queue.
Upgrade: Same procedure as installation. Joomla uses
method="upgrade". All data in the log and queue tables is preserved.
3. Enabling the Plugin
After installation, the plugin must be manually enabled:
- Go to System > Manage > Plugins.
- Search for
semakin_sstorServer-Side Tracking. - Click the plugin name and set Status = Enabled.
- Configure the plugin parameters (see sections below).
4. Basic Configuration
Open the plugin settings: System > Plugins > click the plugin name.
Tab: Basic Settings
| Parameter | Default | Description |
|---|---|---|
| Tracking Enabled | Yes | Global switch for all server-side tracking. |
| Test Mode | No | When on, GA4 events go to the debug endpoint. Disable in production. |
| GDPR Component | StoreJExtensions | Source of user consent (see section 5). |
| Default Consent Layer | 0 (Anonymous) | Used when consent cannot be read or Manual mode is selected. |
| Log Retention (days) | 90 | Records older than this are automatically deleted. |
| Queue Retention (days) | 30 | Processed/failed queue items older than this are deleted. |
| Inline Queue Processing (%) | 5 | Probability of retry queue processing on each request. Set to 0 when using Task Scheduler. |
5. GDPR Consent Setup
The plugin uses a three-layer consent model:
| Layer | Name | What is sent |
|---|---|---|
| L0 | Anonymous | Anonymised events: truncated IP, temporary UUID, no cookies |
| L1 | Analytics | GA4 with client_id, session_id, GCR widget |
| L2 | Marketing | Conversions for GA4/Ads/Sklik/Zbozi/Heureka; hashed email/phone |
Supported GDPR Components
| Component | Detection method |
|---|---|
| StoreJExtensions GDPR (com_gdpr) | JS bridge reads Local Storage, sets cookie semakin_sst_cl |
| Sema Cookie Consent | JS bridge reads Local Storage (scc_cookie_consent), sets cookie semakin_sst_cl |
| CookieYes | Direct cookie read (cookieyes-consent) |
| Manual | Fixed consent level (no detection) |
Important: Cookie Category
The bridge cookie semakin_sst_cl must be categorised as Necessary (Category 1) in your consent component, NOT as Analytics or Marketing. It is a technical cookie that communicates consent status from JS to PHP – it does not track anything.
Timing: The bridge cookie takes effect on the next page load (JS sets the cookie, PHP reads it on the following request). For purchase events this is always fine – the customer has loaded at least 2 pages before checkout.
6. Google Analytics 4
Tab: GA4
| Parameter | Description |
|---|---|
| GA4 Enabled | Enable sending events via Measurement Protocol v2. |
| Measurement ID | Format G-XXXXXXXXXX. Found in GA4 > Admin > Data Streams. |
| API Secret | Measurement Protocol secret. Found in GA4 > Data Streams > Measurement Protocol API secrets. |
| _ga Cookie Name | Default _ga. Change only if using a custom cookie name. |
| Send Anonymous Events (L0) | Send basic events even without consent (anonymised). Recommended: Yes. |
| Client Deduplication | Adds event_id to prevent double-counting if also using gtag.js. |
Tracked Events
| Event | Detection | Min. consent |
|---|---|---|
session_start | First page in session | L0 |
page_view | Every frontend page | L0 |
view_item | URL with view=productdetails | L0 |
view_item_list | URL with view=category | L0 |
add_to_cart | VM hook plgVmOnAddToCart | L0 |
begin_checkout | URL with view=cart | L0 |
purchase | VM hook + DB polling (OPC) | L0 |
Client ID Fallback
Without gtag.js, the _ga cookie does not exist. The plugin automatically creates a fallback cookie semakin_sst_cid with a GA4-compatible format (2-year expiry).
7. Google Ads
Tab: Google Ads
| Parameter | Description |
|---|---|
| Google Ads Enabled | Enable conversion upload via Conversion API v23. |
| Conversion ID | Format AW-XXXXXXXXX (for reference). |
| Conversion Action ID | Numeric ID of the conversion action (not AW- format). |
| Developer Token | From Google Ads API Center. |
| Customer ID | Client account ID (format XXX-XXX-XXXX). |
| MCC Customer ID | Optional. Manager account ID if using MCC. |
| OAuth Client ID | From Google Cloud Console. |
| OAuth Client Secret | Paste into textarea (password fields may truncate). |
| OAuth Refresh Token | Paste into textarea. OAuth consent screen must be in Production mode. |
| Enhanced Conversions | Send hashed email/phone for better attribution. |
Important Notes
- Conversion action type: Must be “Import from clicks” (not “Website”). Website-type actions are for gtag.js.
- Duplicate actions: If the shop previously used a Website-type conversion action (from gtag.js), disable it or set it as secondary to avoid double-counting.
- GCLID/GBRAID/WBRAID: The plugin captures all three click ID types from URL parameters and stores them in cookies (90 days). On devices with limited cookies (Safari, iOS), Google sends
gbraidinstead ofgclid. - Enhanced Conversions for Leads: Must be enabled in Google Ads > Settings > Enhanced conversions for leads. Propagation may take up to several hours.
- Timeout: Google Ads API requests use a 5-second timeout (not 500ms like GA4).
8. Sklik.cz
Tab: Sklik
| Parameter | Description |
|---|---|
| Sklik Enabled | Enable Sklik conversion and retargeting tracking. |
| Conversion Goal ID | Numeric ID from your Sklik conversion code (id parameter). |
| Retargeting List ID | Optional. Retargeting audience ID. |
| Send Hashed Email (EID) | SHA-256 email hash for better attribution (L2 only). |
How It Works
Sklik does not have a server-side API. The plugin injects JavaScript snippets (rc.js) before </body>:
- Retargeting (
rc.retargetingHit) on every page (L0+) - Conversions (
rc.conversionHit) on purchase (L0+) - Consent parameter: Dynamic –
consent:0without marketing consent,consent:1with consent - EID and Zbozi.cz params: Only sent at L2
CSP: If the site uses Content-Security-Policy, add
https://c.seznam.cztoscript-src,connect-src, andimg-src. Addhttps://h.seznam.cztoconnect-src. See the CSP note in the plugin settings.
9. Zbozi.cz
Tab: Zbozi.cz
| Parameter | Description |
|---|---|
| Zbozi.cz Enabled | Enable backend conversion API. |
| Shop ID | Alphanumeric shop identifier from Zbozi.cz admin. |
| PRIVATE_KEY | Secret key for the backend API. Found in Zbozi.cz admin > Conversions > API Key. |
How It Works
Zbozi.cz uses two-component measurement:
- Backend (ZboziSender): HTTP POST to
https://www.zbozi.cz/action/{SHOP_ID}/conversion/backendwith PRIVATE_KEY in the JSON body. - Frontend (via SklikSender):
rc.conversionHit()withzboziIdandzboziTypeparameters. Shares the samerc.jsas Sklik.
Both components are required. Without frontend JS, Zbozi.cz reports an ORPHANED_BACKEND error.
Only
purchaseevents are sent, only at L2.
10. Heureka – Verified by Customers
Tab: Heureka (first section)
| Parameter | Description |
|---|---|
| Verified by Customers Enabled | Enable order registration for satisfaction surveys. |
| Secret Key | API key for Verified by Customers (v2 API). |
| Heureka Variant | CZ (heureka.cz) or SK (heureka.sk). Shared with OCM. |
| Send Customer Email | Required for the survey. Sent in plaintext (L2 consent required). |
| Send Order Products | Send product IDs for product-specific survey questions. |
Opt-out Checkbox
| Parameter | Description |
|---|---|
| Show Opt-out Checkbox | Automatically injects a checkbox into the VirtueMart checkout form. |
| Checkbox Text | Customisable text. Default per Heureka recommendation. |
| Manual Code | HTML/JS code for manual insertion into the template if auto-inject fails. |
The checkbox uses an opt-out model: unchecked = customer agrees to receive the survey; checked = customer opts out. Cookie semakin_sst_heureka_optout=1 (2-hour expiry).
GDPR: Customer email is sent in plaintext to Heureka. It is never stored in plugin logs.
11. Heureka – OCM (Conversion Measurement)
Tab: Heureka (OCM section)
| Parameter | Description |
|---|---|
| Heureka OCM Enabled | Enable conversion measurement via Heureka OCM SDK. |
| API Key | OCM API key (different from the Verified by Customers key!). Found in Heureka admin > Statistics > Conversion Measurement. |
How It Works
- Product pages: SDK with
page=product_detailsets an attribution cookie (hg_ocm_id, 30 days). - Thank-you page: SDK with
page=thank_yousends order data (product IDs, prices, quantities, total, currency). - Only at L2 consent. Cross-request session support for payment gateways.
12. Google Customer Reviews
Tab: Google Customer Reviews
| Parameter | Description |
|---|---|
| GCR Enabled | Enable the Survey Opt-In Widget. |
| Merchant Center ID | Numeric ID from Google Merchant Center. |
| Days Until Delivery | Estimated delivery time (default 5 days). |
| Delivery Country | ISO 3166-1 alpha-2 code (or automatic based on language). |
| Survey Language | BCP 47 language code (e.g. cs, sk, en). |
| Opt-in Dialogue Position | Centre / corners of the screen. |
GCR requires only L1 (Analytics) consent – it is not advertising. Customer email is included in the widget only at L2.
13. Retry Queue and Task Scheduler
When an API call fails, the event is stored in the #__semakin_sst_queue table for automatic retry with exponential backoff (1 min > 5 min > 15 min).
Two Processing Methods
| Method | Configuration |
|---|---|
| Inline processing | Set “Inline Queue Processing” to 5–10%. Processes on random HTTP requests. Good for sites without cron. |
| Joomla Task Scheduler | Create tasks in System > Scheduled Tasks. Set inline processing to 0%. |
Task Scheduler Setup
- Go to System > Scheduled Tasks > New.
- Create “Semakin SST: Process Retry Queue” – run every 15 minutes.
- Create “Semakin SST: Cleanup Old Records” – run once daily.
- Set inline processing to 0% in plugin settings.
- Verify: click “Run Test” – exit code 0 = OK.
Task Scheduler requires a cron job or “lazy cron”. For reliable operation, set up a server cron:
*/5 * * * * php /path/to/joomla/cli/joomla.php scheduler:run > /dev/null 2>&1
14. Logging and Diagnostics
Tab: Logging & Queue
| Parameter | Description |
|---|---|
| Logging Enabled | Global logging switch. |
| Log Level | Minimum level for file log only. DB log always writes regardless of this setting. |
| Log to Database | Write to #__semakin_sst_log. Recommended: always on (required for deduplication). |
| Log to File | Write to logs/semakin_sst.php in the Joomla logs folder. |
| Max Retry Attempts | Maximum retry attempts (default 3). |
Checking the DB Log
SELECT event_name, platform, consent_level, status, http_status, created_at
FROM #__semakin_sst_log
ORDER BY id DESC
LIMIT 20;
Replace #__ with your table prefix.
consent_levelshould be2for purchase events (if the customer has marketing consent).statusshould besentfor successful deliveries.
15. Uninstallation
- Go to System > Manage > Extensions.
- Search for
semakin_sst. - Select and uninstall.
The uninstaller drops both tables (#__semakin_sst_log and #__semakin_sst_queue).
16. Troubleshooting
No Events in Database
- Verify the plugin is enabled (Status = Enabled).
- Check that
services/provider.phpexists in the plugin directory on the server. - Verify the bridge cookie
semakin_sst_clis set (DevTools > Application > Cookies). - If the cookie is missing, check that your GDPR component is configured and the bridge JS is not being stripped.
consent_level Is Always 0
- The bridge cookie
semakin_sst_clis missing or blocked. - Check that
semakin_sst_clis categorised as Necessary in your consent component (not Analytics/Marketing). - On the first page after installation, consent is always L0 (the bridge cookie needs one page load to initialise).
Google Ads Conversions Not Visible in Dashboard
- Verify the conversion action is type “Import from clicks” (not Website).
- Check that GCLID/GBRAID is present in the DB log payload.
- Verify OAuth consent screen is in Production mode (not Testing).
- Check that Enhanced Conversions for Leads is enabled in Google Ads settings.
- If a Website-type conversion action is also active, disable it or set it as secondary.
Sklik Code Not Firing
- Verify
rc.jsis loaded as a synchronous<script>tag (check page source). - If the site uses CSP, add the required domains (see CSP note in Sklik tab).
- Check browser console for errors.
Zbozi.cz ORPHANED_BACKEND Error
- Both backend API and frontend JS (
rc.conversionHitwithzboziId) are required. - Verify that Sklik is enabled (Sklik’s
rc.jshandles both Sklik and Zbozi.cz frontend).
Heureka HTTP 400 “Missing expected key email”
- Verify that “Send Customer Email” is enabled in Heureka settings.
- The email requires L2 consent.
Purchase Events Not Detected (OPC)
- One Page Checkout plugins bypass VirtueMart hooks. The plugin uses DB polling (
detectUnloggedPurchases) as a fallback. - Verify that DB logging is enabled (required for deduplication).
- Check that requests are not coming from bots (empty cookies = skipped).
How Tracking Works (Overview)
- A visitor loads a page on the e-shop.
- The plugin detects the page type (product, category, cart, etc.) from URL parameters.
- Events are collected (
page_view,view_item,begin_checkout, etc.). - The consent level is determined from the GDPR component (via bridge cookie).
- Events are anonymised according to the consent level.
- Server-side senders dispatch events to the enabled platforms (GA4, Google Ads, Zbozi, Heureka).
- JavaScript senders inject code before
</body>(Sklik, Heureka OCM, GCR). - For purchases: VM hook
plgVmConfirmedOrderor DB polling (OPC) detects the order. - Failed API calls are queued for automatic retry.
Launch Checklist
- Plugin installed and enabled
- GDPR component selected and configured
- Bridge cookie
semakin_sst_clcategorised as Necessary - GA4: Measurement ID and API Secret configured
- Google Ads: Conversion action created as “Import from clicks”
- Google Ads: OAuth credentials in textarea fields, consent screen in Production
- Google Ads: Enhanced Conversions for Leads enabled
- Sklik: Conversion ID and Retargeting ID configured
- Zbozi.cz: Shop ID and PRIVATE_KEY configured
- Heureka: API key configured, opt-out checkbox enabled
- Heureka OCM: OCM API key configured (different from Verified key)
- GCR: Merchant Center ID configured
- CSP headers updated (if applicable)
- DB logging enabled
- Test Mode DISABLED
- Inline queue processing set (or Task Scheduler configured)
- Test purchase completed and verified in DB log and platform dashboards