PHPackages                             montu/module-affiliate - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. montu/module-affiliate

ActiveMagento2-module[Utility &amp; Helpers](/categories/utility)

montu/module-affiliate
======================

Montu Affiliate Tracking Extension for Magento 2 - Captures affiliate referral codes, attributes orders, sends signed order webhooks, and renders a white-label affiliate storefront.

v1.0.0(1mo ago)021OSL-3.0PHPPHP &gt;=8.1

Since Jun 23Pushed 1mo agoCompare

[ Source](https://github.com/montu-io/magento)[ Packagist](https://packagist.org/packages/montu/module-affiliate)[ Docs](https://montu.io)[ RSS](/packages/montu-module-affiliate/feed)WikiDiscussions main Synced 2w ago

READMEChangelogDependencies (10)Versions (2)Used By (0)

Montu Affiliate — Extensión de Magento 2 (`montu/module-affiliate`)
===================================================================

[](#montu-affiliate--extensión-de-magento-2-montumodule-affiliate)

Paquete Composer del módulo **`Montu_Affiliate`**: captura códigos de afiliados en el storefront y envía webhooks firmados con la información de las órdenes a la plataforma Montu.

Este directorio **es el paquete Composer** (raíz = raíz del módulo). No contiene una instalación de Magento ni entorno Docker — solo el código del módulo, instalable vía Composer en cualquier proyecto Magento 2.

✨ Características
-----------------

[](#-características)

- ✅ **No Invasivo** — no modifica tablas core de Magento (crea las suyas)
- ✅ **Asíncrono** — no bloquea el checkout; los webhooks se entregan por cron
- ✅ **Fail-safe** — los observers nunca dejan escapar excepciones
- ✅ **Reintentos automáticos** — 5 intentos con backoff exponencial (1/5/15/30/60 min)
- ✅ **White-label** — el storefront del afiliado adopta los colores y la tipografía de cualquier tema de la tienda (o se configuran a mano en el admin)

---

📦 Instalación vía Composer
--------------------------

[](#-instalación-vía-composer)

El paquete está publicado en **Packagist público**, así que la instalación es directa, sin configurar repositorios:

```
composer require montu/module-affiliate
```

Requisitos: Magento 2.4.x y PHP 8.1+.

Instalación para desarrollo (monorepo / repositorio `path`)Este paquete vive como subcarpeta `magento/` del monorepo de Montu. Para trabajar contra el código en disco (cambios en vivo), apunta Composer a la carpeta con un repo `path`:

```
// composer.json del proyecto Magento
{
  "repositories": [
    { "type": "path", "url": "../monorepo/magento", "options": { "symlink": true } }
  ]
}
```

```
composer require montu/module-affiliate:@dev
```

`symlink: true` enlaza la carpeta; usa `"symlink": false` para que Composer **copie** el paquete (recomendado en builds/deploys).

> El `composer.json` **no fija `version`**: Composer toma la versión de los **tags git** del repo publicado en Packagist (`git tag v1.0.0`), así que puedes fijar `^1.0` si lo necesitas.

### Activar el módulo (después de `composer require`)

[](#activar-el-módulo-después-de-composer-require)

```
bin/magento module:enable Montu_Affiliate
bin/magento setup:upgrade            # crea montu_affiliate_tracking + montu_affiliate_webhook_log
bin/magento setup:di:compile         # tras cambios de DI / constructores
bin/magento cache:clean
```

---

⚙️ Configuración
----------------

[](#️-configuración)

**Stores → Configuration → Montu → Affiliate Tracking**

CampoDescripciónDefaultEnable ModuleActiva la extensiónNoURL ParameterParámetro a capturar`_m_aff`Cookie NameNombre de la cookie`_montu_aff_ref_code`Cookie LifetimeDías de duración15Enable WebhookActiva webhooksNoWebhook URLURL de tu endpoint-API KeyTu API key (almacenada **encriptada**)-### Storefront del afiliado (sección **Affiliate Storefront**)

[](#storefront-del-afiliado-sección-affiliate-storefront)

CampoDescripciónDefaultEnable Storefront PageActiva la ruta `/storefront/{code}`NoRoute Path PrefixPrefijo de la URL pública`storefront`Page HeadingTítulo de la página`Recommended products`Recommendations Endpoint URLEndpoint Montu de productos recomendados-Storefront LanguageIdioma de la página: `en_US`, `es_ES` o `es_CL` (Chile)`en_US`Max ProductsMáximo de productos a mostrar12> **Idioma:** Magento **no** hace fallback de `es_CL` → `es_ES`, por eso el módulo incluye traducciones propias para Chile (`i18n/es_CL.csv`). Para una tienda chilena, selecciona **Spanish (Chile)**.

### Apariencia / White-label (sección **Appearance**)

[](#apariencia--white-label-sección-appearance)

El storefront es **white-label**: adopta los colores y la tipografía de la tienda automáticamente. Todos los colores, bordes, radios de tarjeta y la fuente se controlan por variables CSS.

CampoDescripciónDefaultTheme Mode`Auto` (muestrea el tema de la tienda en runtime), `Manual` (usa los colores de abajo) u `Off` (estilo neutro)`Auto`Accent / Primary ColorColor principal (botones, lista activa, resaltados). Acepta `#hex`, `rgb()`/`rgba()` o nombre CSS(muestreado)Accent Text ColorColor de texto legible sobre el acento`#ffffff`Body Text ColorColor de texto del storefront (vacío → hereda el tema)(heredado)Muted Text ColorColor de texto secundario (conteos, subtítulos)`#6d6d6d`Border ColorColor de bordes/divisores`#e3e3e3`Card Background ColorFondo de las tarjetas de producto`#ffffff`Card Corner RadiusRadio de esquina de las tarjetas (`10px`, `0`, `0.5rem`)`10px`Font FamilyStack de fuentes del storefront (vacío → hereda la fuente del tema)(heredado)- **Auto:** sin configurar nada, el storefront muestrea el color del botón primario, el color de texto y la fuente del tema vivo de la tienda (Luma, custom o re-skin) y se adapta. Los valores de arriba sirven como semilla/fallback.
- **Manual:** fija exactamente los colores configurados, sin muestreo runtime. Los campos vacíos usan el default neutro.
- **Off:** estilo neutro por defecto (sin muestreo, ignora los colores).

---

🛍️ Tienda del Afiliado (`/storefront/{code}`)
---------------------------------------------

[](#️-tienda-del-afiliado-storefrontcode)

Un visitante puede entrar con un código de afiliado de **dos formas**, y en ambas se guarda la cookie con el código:

1. **Query param** — `https://tienda.com/?_m_aff=ABC123` (capturado por JS).
2. **Ruta storefront** — `https://tienda.com/storefront/ABC123`, que además **renderiza una página con los productos que ese afiliado recomienda**.

La ruta la resuelve un **router personalizado** (`Controller/Router.php`) que toma el código del path y reenvía a `Controller/Storefront/Index.php`. El controlador valida el código (`^[a-zA-Z0-9_\-]{1,100}$`), **escribe la cookie en el servidor** (mismo nombre/duración que la captura por JS) y renderiza la página, declarada **`cacheable="false"`** para que el Full Page Cache / Fastly nunca la sirva cacheada.

Los productos se obtienen vía `Service/RecommendationClient.php` desde el endpoint de recomendaciones de Montu (`GET /montu/api/v1/ecommerce/magento/recommendations/{store_id}/{code}`), firmado con HMAC-SHA256 (igual que el webhook). Configura *Recommendations Endpoint URL* en admin con la URL terminada en el id de tienda. La forma esperada del JSON está documentada en `RecommendationClient::parseResponse()`. Si el endpoint falla o no responde, la página degrada con elegancia (datos de ejemplo) en vez de romperse.

> **Full Page Cache / Fastly:** la ruta `/storefront/{code}` está declarada `cacheable="false"`, así que el FPC/Fastly nunca la cachea (es por-afiliado y escribe la cookie). El JS de captura (`tracking.js`) lee el parámetro `?_m_aff=` en el cliente, así que funciona aunque el resto de las páginas estén cacheadas.
>
> **Queue-it / Klevu / reglas de path:** si la tienda tiene una sala de espera virtual o un proxy de búsqueda delante del storefront, agrega el prefijo de la ruta (`/storefront/...`) a la lista de paths permitidos para que no sea interceptado.

---

🔄 Cómo Funciona
---------------

[](#-cómo-funciona)

```
?_m_aff=ABC123 → JS guarda cookie
   → (compra) → Observer encola fila pending en montu_affiliate_webhook_log
   → Cron/ProcessWebhooks (cada 5 min) → POST firmado (HMAC-SHA256) a tu endpoint

```

1. **Captura** — `view/frontend/web/js/tracking.js` guarda `?_m_aff=` en cookie.
2. **Persistir al carrito** — `Observer/SaveAffiliateToQuote` (`checkout_cart_save_after`).
3. **Vincular a orden** — `Observer/CopyAffiliateToOrder` (`sales_model_service_quote_submit_success`).
4. **Encolar webhook** — `Observer/SendOrderWebhook` (`checkout_submit_all_after`) si la orden tiene código de afiliado **o** cupón.
5. **Entregar async** — `Cron/ProcessWebhooks` → `Service/WebhookService` (Curl + HMAC + reintentos).

---

📊 Sistema de Reintentos
-----------------------

[](#-sistema-de-reintentos)

Intento1º2º3º4º5ºEspera1 min5 min15 min30 min1 horaTras el 5º intento el webhook se marca como `max_retries`.

---

📨 Formato del Webhook
---------------------

[](#-formato-del-webhook)

### Headers

[](#headers)

```
Content-Type: application/json
X-Montu-Api-Key:
X-Montu-Store-Domain:
X-Montu-Store-Code:
X-Montu-Timestamp:
X-Montu-Signature:

```

### Body (JSON)

[](#body-json)

```
{
    "webhook_version": "1.0",
    "event": "order.placed",
    "timestamp": "2024-01-15T10:30:00+00:00",
    "store": { "code": "default", "name": "Mi Tienda", "base_url": "https://tutienda.com/" },
    "order": { "increment_id": "000000123", "grand_total": 150.00, "currency_code": "USD" },
    "affiliate": { "code": "ABC123" },
    "customer": { "email": "customer@example.com" },
    "items": [],
    "billing_address": {},
    "shipping_address": {}
}
```

El backend valida la firma **y** rechaza timestamps de más de 5 minutos (anti-replay). El receptor vive en el backend Django: `back/montu/rest_api/v1/views/ecommerce/magento/`. **Cualquier cambio al payload aquí requiere el cambio correspondiente allá, en sincronía.**

---

🧪 Testing Local
---------------

[](#-testing-local)

1. URL de prueba en [webhook.site](https://webhook.site).
2. En admin → Webhook URL: `https://webhook.site/tu-uuid`, API Key: `test-key-123`.
3. Visitar `https://tu-tienda.test/?_m_aff=TEST123`, verificar cookie, crear una orden, y:

```
bin/magento cron:run                  # fuerza Cron/ProcessWebhooks
tail -f var/log/montu_affiliate.log   # logs del módulo
# SELECT * FROM montu_affiliate_webhook_log;
```

---

📁 Estructura del paquete
------------------------

[](#-estructura-del-paquete)

```
magento/                       ← raíz del paquete Composer (montu/module-affiliate)
├── composer.json              # name + type magento2-module + autoload PSR-4
├── registration.php           # ComponentRegistrar::register(MODULE, 'Montu_Affiliate', __DIR__)
├── etc/                       # module.xml, di.xml, events.xml, crontab.xml, db_schema.xml, adminhtml/system.xml …
├── Model/                     # Config, AffiliateTracking, WebhookLog, repositories, ResourceModels
├── Api/                       # interfaces de repositorios
├── Observer/                  # SaveAffiliateToQuote, CopyAffiliateToOrder, SendOrderWebhook
├── Service/                   # WebhookService (Curl + HMAC + reintentos), RecommendationClient
├── Cron/                      # ProcessWebhooks
├── Controller/               # Router + Storefront/Index (ruta /storefront/{code})
├── Block/ + ViewModel/        # adminhtml order view, storefront config
└── view/                      # frontend (tracking.js/.phtml, storefront) + adminhtml

```

### Tablas propias (nunca toca core)

[](#tablas-propias-nunca-toca-core)

- `montu_affiliate_tracking` — código de afiliado por quote/orden
- `montu_affiliate_webhook_log` — cola de webhooks con status + retry count

---

🗑️ Desinstalación
-----------------

[](#️-desinstalación)

```
bin/magento module:disable Montu_Affiliate
composer remove montu/module-affiliate
bin/magento setup:upgrade
```

---

Requisitos
----------

[](#requisitos)

- Magento 2.4.x, PHP 8.1+ (ver `composer.json` para los módulos Magento requeridos)
- Cron de Magento funcionando (`* * * * * php bin/magento cron:run`)

Licencia
--------

[](#licencia)

Open Software License 3.0 (OSL-3.0) — ver [`LICENSE.txt`](LICENSE.txt).

Soporte
-------

[](#soporte)

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance90

Actively maintained with recent releases

Popularity9

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

45d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/c07bf95df2ee8594f66d094cf25d8c9d2a5c905d18c584b1abddfddb177b5344?d=identicon)[vichoramosw96](/maintainers/vichoramosw96)

---

Top Contributors

[![vichomontu10](https://avatars.githubusercontent.com/u/193319158?v=4)](https://github.com/vichomontu10 "vichomontu10 (32 commits)")

---

Tags

magentowebhookmagento2referralaffiliate-trackingaffiliatemagento modulemontu

### Embed Badge

![Health badge](/badges/montu-module-affiliate/health.svg)

```
[![Health](https://phpackages.com/badges/montu-module-affiliate/health.svg)](https://phpackages.com/packages/montu-module-affiliate)
```

###  Alternatives

[mollie/magento2

Mollie Payment Module for Magento 2

1142.0M17](/packages/mollie-magento2)[buckaroo/magento2

Buckaroo Magento 2 extension

32426.0k8](/packages/buckaroo-magento2)[run-as-root/magento2-prometheus-exporter

Magento2 Prometheus Exporter

69362.0k](/packages/run-as-root-magento2-prometheus-exporter)[dotdigital/dotdigital-magento2-extension

Dotdigital for Magento 2

50406.2k23](/packages/dotdigital-dotdigital-magento2-extension)[loki/magento2-components

Core module for defining Alpine.js components with advanced AJAX features

1015.1k27](/packages/loki-magento2-components)[yireo/magento2-emailtester2

Preview transactional emails and test send them in your backend

34441.8k](/packages/yireo-magento2-emailtester2)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
