# Eseményszűrők

> Az eseményadatok testreszabása minden pixelhez JavaScript (böngésző) és PHP (szerveroldali) szűrőkkel, eseménynév-leképezéssel és hibakereséssel.

Az eseményszűrőkkel az összes pixel eseményadatait testre szabhatod JavaScript (a böngészőben) és PHP (a szerveren futó) szűrőkkel.

## Miért a parancssorban regisztráld a szűrőket?

A szűrőidet mindig a Pixel Manager [parancssorába](https://hub.hellowp.io/hu/plugins/woocommerce-pixel-manager/fejlesztoknek-command-queue/) csomagold:

```js
window._pmwq = window._pmwq || [];
window._pmwq.push(function () {
    pmw.hooks.addFilter('pmw_pixel_data_facebook', 'my-plugin', function (pixelData) {
        pixelData.custom_data.custom_field = 'my_value';
        return pixelData;
    });
});
```

A gyorsítótárazó rendszerek és a JavaScript-optimalizálók összekeverhetik, összevonhatják vagy késleltethetik a szkriptek betöltését. A parancssor megbízhatóan biztosítja, hogy a szűrőid a Pixel Manager betöltése után regisztrálódjanak, így elkerülhető a versenyhelyzet és az inicializálási hiba. Nélküle a `pmw.hooks` még nem létezhet, és a kódod csendben hibázik.

Hozzáadás a WordPresshez (a gyermektéma `functions.php` fájljába):

```php
add_action('wp_head', function () {
    ?>
    <script>
    window._pmwq = window._pmwq || [];
    window._pmwq.push(function () {
        pmw.hooks.addFilter('pmw_pixel_data_facebook', 'my-plugin', function (pixelData) {
            pixelData.custom_data.custom_field = 'my_value';
            return pixelData;
        });
    });
    </script>
    <?php
}, 1);
```

## A szűrők megtervezése

A szűrők írása előtt gondold végig, hol dolgozódnak fel az események.

### Böngészőoldali és szerveroldali események

**Böngészőoldali események** (a böngészőben dolgozódnak fel):

- minden esemény, ha a szerver-szerver követés ki van kapcsolva
- az olyan események, mint az `add_to_cart`, `view_item`, `begin_checkout`
- a vásárlási események csak akkor, ha a böngészőn keresztül dolgozódnak fel

**Szerveroldali események** (a szerveren dolgozódnak fel):

- a vásárlási események, ha a szerver-szerver követés be van kapcsolva (Facebook CAPI, TikTok EAPI, Pinterest APIC, Snapchat CAPI)
- a Google Analytics vásárlási eseményei, ha a Measurement Protocol be van kapcsolva
- ezek mindig a szerverről mennek, soha nem a böngészőn át

Miért szerveroldali a vásárlási esemény? A böngészőalapú követést blokkolhatják a hirdetésblokkolók, a böngészőbővítmények, az adatvédelmi beállítások vagy a hálózati szűrők. Bekapcsolt szerver-szerver követésnél a vásárlási eseményeket a szerver állítja össze, és közvetlenül a hirdetési platformoknak küldi, a böngészőt teljesen megkerülve, így a kliensoldali blokkolás nem éri el őket. Az ára, hogy ezek teljesen független láncban dolgozódnak fel, ezért külön szűrők kellenek hozzájuk.

> **Fontos: vásárlási események szerver-szerver követéssel.** Aktív szerver-szerver követésnél a vásárlási eseményeket kizárólag a szerver állítja össze és küldi, a WooCommerce-rendelésből, egy rendelési státuszváltáskor. Ezért:
>
> - A böngészőoldali szűrők nem hatnak rájuk.
> - Az alább leírt `pmw_server_event_payload_*` lánc sem hat rájuk. Az a láncot a szerverre továbbított böngészőeseményeket dolgozza fel, a végpontja pedig szándékosan elutasítja a `purchase` eseményt, ezért a `pmw_server_event_payload_event_purchase` vagy `pmw_server_event_payload_facebook_purchase` szűrőre írt visszahívás soha nem fut le.

Mit használj helyette:

| Cél | Szűrő |
|---|---|
| Egy rendelés szerveroldali vásárlásának elnyomása | `pmw_skip_s2s_purchase_event` (lásd: [Szerveroldali szűrők](https://hub.hellowp.io/hu/plugins/woocommerce-pixel-manager/fejlesztoknek-php-szurok-szerveroldal/)) |
| A GA4 Measurement Protocol vásárlási adatcsomagjának módosítása | `pmw_server_event_payload_google_analytics`, `pmw_server_event_payload_google_analytics_purchase`, `pmw_server_event_payload_post`: ezeket a Measurement Protocol a saját adatcsomagjára alkalmazza |
| Bármely célhely (Meta, TikTok, Pinterest, Snapchat, Reddit, Microsoft Advertising és a többi) szerveroldali vásárlási adatcsomagjának módosítása | `pmw_server_purchase_payload` és `pmw_server_purchase_payload_{célhely}` (Pro). A közvetlen küldésnél és a SweetCode Cloud útvonalon is lefutnak |

Példa, amely az ki nem fizetett rendelések szerveroldali vásárlását elnyomja:

```php
add_filter('pmw_skip_s2s_purchase_event', function ($skip, $order) {
    if (!$order instanceof WC_Order) {
        return $skip;
    }
    return $order->is_paid() ? $skip : true;
}, 10, 2);
```

A teljes mintát, azt is, hogy mely rendelési státuszváltások váltják ki a szerveroldali vásárlást, a [Státuszvezérelt vásárlási konverziók](https://hub.hellowp.io/hu/plugins/woocommerce-pixel-manager/fejlesztoknek-receptek-statuszvezerelt-vasarlas/) recept tartalmazza.

## Böngészőoldali szűrők (JavaScript)

### A szűrőlánc

Az események négy szakaszon mennek át. Minden szűrőnek vissza kell adnia a módosított adatot.

1. `pmw_event_payload_pre`: a pixelátalakítások előtt (az esemény alapadatainak módosítása)
2. `pmw_pixel_data_{pixel}`: pixelenkénti átalakítás (például `pmw_pixel_data_facebook`)
3. `pmw_event_payload_{event}`: eseménytípusonként (például `pmw_event_payload_purchase`)
4. `pmw_event_payload_post`: záró szakasz (naplózás, hibakeresés)

Támogatott pixelek: `facebook`, `google_ads`, `google_analytics`, `tiktok`, `pinterest`, `snapchat`, `linkedin`, `microsoft_ads`, `twitter`, `reddit`, `taboola`, `outbrain`.

Támogatott események: `page_view`, `add_to_cart`, `view_item`, `view_item_list`, `begin_checkout`, `add_payment_info`, `add_to_wishlist`, `search`, `purchase`.

### Az API

```js
pmw.hooks.addFilter(hookName, namespace, callback, priority)
pmw.hooks.removeFilter(hookName, namespace)
pmw.hooks.hasFilter(hookName, namespace)
```

- `namespace`: egyedi azonosító az ütközések elkerülésére (például `'my-plugin/feature'`)
- `priority`: a végrehajtás sorrendje (alapérték 10, a kisebb szám korábban fut)
- `null` visszaadásával megakadályozhatod az esemény elsülését

### Példák

#### Egyedi Facebook-paraméterek hozzáadása

```js
window._pmwq.push(function () {
    pmw.hooks.addFilter('pmw_pixel_data_facebook', 'my-store', function (pixelData) {
        pixelData.custom_data = pixelData.custom_data || {};
        pixelData.custom_data.store_location = 'Budapest';
        pixelData.custom_data.user_segment = 'premium';
        return pixelData;
    });
});
```

#### Árak globális módosítása

```js
window._pmwq.push(function () {
    pmw.hooks.addFilter('pmw_event_payload_pre', 'price-modifier', function (payload) {
        if (payload.event_data?.product?.price) {
            payload.event_data.product.price *= 1.15;
        }
        return payload;
    });
});
```

#### Szűrés eseménytípus szerint

```js
window._pmwq.push(function () {
    pmw.hooks.addFilter('pmw_event_payload_purchase', 'purchase-tags', function (payload) {
        if (payload.event_data?.order_total > 500) {
            payload.event_data.high_value = true;
        }
        return payload;
    });
});
```

#### Események feltételes tiltása

```js
window._pmwq.push(function () {
    pmw.hooks.addFilter('pmw_pixel_data_facebook', 'admin-filter', function (pixelData) {
        if (window.userIsAdmin) {
            return null; // az esemény blokkolása
        }
        return pixelData;
    });
});
```

#### A végrehajtási sorrend beállítása prioritással

```js
window._pmwq.push(function () {
    pmw.hooks.addFilter('pmw_event_payload_pre', 'early-filter', function (payload) {
        payload.event_data.processed_by = ['early-filter'];
        return payload;
    }, 5);

    pmw.hooks.addFilter('pmw_event_payload_pre', 'late-filter', function (payload) {
        payload.event_data.processed_by.push('late-filter');
        return payload;
    }, 10);
});
```

## Eseménykezelő szűrők (JavaScript)

Két további böngészőoldali szűrő nem az adatcsomagot módosítja, hanem azt, hogyan bánik a könyvtár az eseménnyel. Ugyanúgy regisztrálod őket, mint az adatcsomag-szűrőket, a parancssoron át.

### `pmw_duplicate_event_window`

Egy vásárlói tevékenység gyakran kétszer jut el a könyvtárhoz. A WooCommerce és a környezete ugyanazt a kosárba tételt kattintásként és saját eseményként is jelzi, a sablonok újrarajzolják a kötött gombot tartalmazó területeket, az előre kiválasztott változatot pedig az oldalbetöltés és a WooCommerce saját változatesemény is jelenti. Minden menet saját eseményazonosítót állít elő, így a célplatform nem ismeri fel az ismétlést, és a beavatkozást kétszer számolja, mind a böngészőpixelen, mind a szerveroldali API-n.

A Pixel Manager ezért elnyom minden olyan eseményt, amely azonos az utolsó 1000 ezredmásodpercben jelentettel. Azonos az, aminek ugyanaz az eseménynév, ugyanaz az URL, ugyanaz a termék, tranzakció, szállítási szint és fizetési mód. Ugyanaz a termék navigáció utáni újranézése tehát önálló esemény, ahogy a más kifejezésre való keresés is. A `purchase` esemény ezt az őrt soha nem kapja, mert azt már erősebb mechanizmus rendelésenként egyre korlátozza.

A szűrővel bővítheted, szűkítheted az ablakot, vagy `0` visszaadásával kikapcsolhatod az őrt.

```js
window._pmwq = window._pmwq || [];
window._pmwq.push(function () {
    pmw.hooks.addFilter('pmw_duplicate_event_window', 'my-plugin', function (windowMs, eventName, eventData) {
        // a kosárba tételnél 2,5 másodpercre bővített ablak
        if (eventName === 'add_to_cart') {
            return 2500;
        }
        return windowMs;
    });
});
```

> **Figyelem:** A `0` visszaadása minden olyan téma- és bővítménykombinációnál visszahozza a dupla számolást, amely okozza. Inkább növeld az ablakot, és csak arra az időre kapcsold ki, amíg kinyomozod, honnan jön egy duplikátum.

### `pmw_navigation_events`

Egyes események olyan kattintásra sülnek el, amely rögtön elnavigálja a böngészőt. A tipikus példa a `begin_checkout`: a pénztárhoz vezető gomb kattintására sül el, amely betölti a pénztár oldalt. Ezeknél az eseményeknél a szerver-szerver küldést szinkron módon kell kiadni, még az oldal elhagyása előtt. Különben az aszinkron gazdagítási lépések az elnavigálás utánra halasztják a küldést, a `navigator.sendBeacon` el sem készül, és a szerveroldali esemény csendben elvész, miközben a böngészőpixel elsül.

A lista alapból a `begin_checkout` eseményt tartalmazza. Add hozzá a saját eseményneveidet, ha egy egyedi sablon navigáló hivatkozásra süt el egyet.

```js
window._pmwq = window._pmwq || [];
window._pmwq.push(function () {
    pmw.hooks.addFilter('pmw_navigation_events', 'my-plugin', function (events) {
        events.push('add_payment_info');
        return events;
    });
});
```

Belső eseménynevek tömbjét adj vissza (a lista lent: Belső eseménynevek).

> **Megjegyzés:** A szinkron küldés kihagyja a gazdagítás aszinkron részeit, ezért egy ilyen listán lévő esemény valamivel kevesebb felhasználói adatot hordozhat, mint ugyanaz az esemény egy olyan oldalon, amely a helyén marad. Ez az ár: kevesebb adat egy olyan eseményen, amely megérkezik, ahelyett hogy egy teljes esemény sosem érkezne meg.

## Szerveroldali szűrők (PHP)

### A szűrőlánc

A szerverre továbbított böngészőesemények (Facebook CAPI, TikTok EAPI, Pinterest APIC, Snapchat CAPI) öt szakaszon mennek át:

1. `pmw_server_event_payload_pre`: a pixelfeldolgozás előtt (az összes pixelre egyszerre)
2. `pmw_server_event_payload_{pixel}`: pixelenként, az összes eseményre (például `facebook`)
3. `pmw_server_event_payload_event_{event}`: eseményenként, az összes pixelre (például `purchase`)
4. `pmw_server_event_payload_{pixel}_{event}`: egy adott pixel és egy adott esemény (például `facebook_purchase`)
5. `pmw_server_event_payload_post`: záró szakasz az API-nak küldés előtt

**A vásárlási események nem mennek át ezen a láncon.** Ezekhez a szűrőkhöz a szerverre továbbított böngészős tölcsér-események jutnak el: `view_item`, `add_to_cart`, `begin_checkout` és a többi. A vásárlási eseményt a WooCommerce-rendelésből, rendelési státuszváltáskor, külön úton állítja össze a bővítmény, a láncot tápláló végpont pedig a `purchase` eseményt kereken elutasítja. A `pmw_server_event_payload_event_purchase` vagy a `pmw_server_event_payload_{pixel}_purchase` szűrőre írt visszahívás ezért soha nem fut le, egy kivétellel: a Google Analytics 4 Measurement Protocol a 2., 4. és 5. szakaszt a saját vásárlási adatcsomagjára alkalmazza, így a `pmw_server_event_payload_google_analytics_purchase` GA4-re működik.

A szerveroldali vásárlás elnyomásához használd a `pmw_skip_s2s_purchase_event` szűrőt, a tartalmának módosításához a `pmw_server_purchase_payload` szűrőt (lásd: [Szerveroldali szűrők](https://hub.hellowp.io/hu/plugins/woocommerce-pixel-manager/fejlesztoknek-php-szurok-szerveroldal/)). A teljes mintát a [Státuszvezérelt vásárlási konverziók](https://hub.hellowp.io/hu/plugins/woocommerce-pixel-manager/fejlesztoknek-receptek-statuszvezerelt-vasarlas/) recept tartalmazza.

> **Megjegyzés:** A Pro változatban a szerveroldali Google Analytics `refund` események is átmennek ezen a láncon, `refund` eseménynéven (`pmw_server_event_payload_google_analytics_refund`). A részleges és a teljes visszatérítés adatcsomagja is. Ha a visszatérítések jelentését teljesen ki akarod kapcsolni, használd a `pmw_google_analytics_refund_tracking` szűrőt.

### Példák

#### Az összes kosárba tételi esemény módosítása (minden pixelnél)

```php
add_filter('pmw_server_event_payload_event_add_to_cart', function ($pixel_data, $pixel_name, $event_name) {
    $pixel_data['custom_data']['event_timestamp'] = time();

    if (isset($pixel_data['custom_data']['value'])) {
        $value = $pixel_data['custom_data']['value'];
        $pixel_data['custom_data']['value_tier'] = $value < 50 ? 'low' : ($value < 200 ? 'medium' : 'high');
    }
    return $pixel_data;
}, 10, 3);
```

#### Egyedi adat hozzáadása csak a Facebookhoz

```php
add_filter('pmw_server_event_payload_facebook', function ($pixel_data, $pixel_name) {
    $pixel_data['user_data']['subscription_status'] = 'premium';
    return $pixel_data;
}, 10, 2);
```

#### Egy adott pixel és esemény megcélzása

```php
add_filter('pmw_server_event_payload_facebook_begin_checkout', function ($pixel_data, $pixel_name, $event_name) {
    $user_id = get_current_user_id();
    if ($user_id) {
        $ltv = get_user_meta($user_id, 'customer_ltv', true);
        if ($ltv > 1000 && isset($pixel_data['custom_data']['value'])) {
            $pixel_data['custom_data']['value'] *= 1.2;
        }
    }
    return $pixel_data;
}, 10, 3);
```

#### Események feltételes tiltása

```php
// Kosárba tétel blokkolása 10 alatti értéknél
add_filter('pmw_server_event_payload_event_add_to_cart', function ($pixel_data, $pixel_name, $event_name) {
    if (isset($pixel_data['custom_data']['value']) && $pixel_data['custom_data']['value'] < 10) {
        return null;
    }
    return $pixel_data;
}, 10, 3);

// Szerveroldali vásárlás blokkolása 10 alatti rendelésértéknél
add_filter('pmw_skip_s2s_purchase_event', function ($skip, $order) {
    if (!$order instanceof WC_Order) {
        return $skip;
    }
    return ((float) $order->get_total() < 10) ? true : $skip;
}, 10, 2);

// Egy pixel összes eseményének blokkolása feltétel esetén
add_filter('pmw_server_event_payload_facebook', function ($pixel_data) {
    if (some_condition()) {
        return null;
    }
    return $pixel_data;
});
```

## Az eseményadatcsomag szerkezete

```js
{
    event: 'add_to_cart',
    event_data: {
        product: {
            id: 123,
            name: 'Product Name',
            price: 99.99,
            quantity: 1,
            currency: 'USD',
            categories: ['Electronics']
        }
    },
    pixels: {
        facebook: {
            event_name: 'AddToCart',
            event_id: 'unique-id',
            custom_data: { /* ... */ }
        },
        google_analytics: {
            event_name: 'add_to_cart',
            event_data: { /* ... */ }
        }
    }
}
```

## Ajánlott gyakorlatok

1. **Mindig add vissza az értéket.** A szűrőnek a módosított adatot vagy `null` értéket (a blokkoláshoz) kell visszaadnia.
2. **Egyedi névteret használj.** Formátum: `'plugin-name/feature'` vagy `'company-name/modifier'`.
3. **Csomagold a `_pmwq` parancssorba.** Így a Pixel Manager a szűrőid előtt betöltődik.
4. **Ellenőrizd, hogy az adat létezik-e.** Használj opcionális láncolást: `payload.event_data?.product?.price`.
5. **Megfelelő prioritást használj.** Az alapérték 10, a kisebb szám korábban fut.
6. **Alaposan tesztelj.** A böngészőkonzolban látod a szűrők lefutásának naplóit.

## Hibakeresés

### Konzolnaplózás

A szűrők lefutását a bővítmény a böngészőkonzolba naplózza, például:

```text
🔍 Pre-processing filter called: add_to_cart
📊 GA pixel data filter called: add_to_cart
```

### Az adatcsomagok megvizsgálása

```js
window._pmwq.push(function () {
    pmw.hooks.addFilter('pmw_event_payload_post', 'debugger', function (payload, eventName) {
        console.log(`Esemény: ${eventName}`, payload);
        return payload;
    }, 999); // legutoljára fut
});
```

### PHP-s hibakeresés

```php
add_filter('pmw_server_event_payload_post', function ($pixel_data, $pixel_name) {
    if (defined('WP_DEBUG') && WP_DEBUG) {
        error_log("Küldés: {$pixel_data['event_name']} -> {$pixel_name}: " . json_encode($pixel_data));
    }
    return $pixel_data;
}, 10, 2);
```

## Áttérés a régi rendszerről

Ha jQuery-s eseményfigyelőket használtál:

Régi:

```js
jQuery(document).on("pmw:add-to-cart", function (event, product) {
    product.price = product.price * 1.1;
});
```

Új (ajánlott, szűrőkkel):

```js
window._pmwq.push(function () {
    pmw.hooks.addFilter('pmw_event_payload_add_to_cart', 'namespace', function (payload) {
        payload.event_data.product.price *= 1.1;
        return payload;
    });
});
```

Alternatíva, a nyilvános API-események használatával: ha csak figyelni akarod az eseményeket (nem módosítani), használhatod a nyilvános API-eseményeket a szűrők helyett.

```js
window._pmwq.push(function () {
    jQuery(document).on('pmw:event:add-to-cart', function (event, payload) {
        console.log('Kosárba tett termék:', payload.event_data.product);
        console.log('Pixelspecifikus adat:', payload.pixels);

        // a saját követőd
        myCustomTracker.track('add_to_cart', payload.event_data);
    });
});
```

A `pmw:event:*` események a teljes, feldolgozott adatcsomagot adják, az összes pixel-átalakítással együtt. Az elérhető események listája a [Command queue](https://hub.hellowp.io/hu/plugins/woocommerce-pixel-manager/fejlesztoknek-command-queue/) fejezetben van.

## Eseménynév-leképezés

A Pixel Manager belső, snake_case eseményneveket használ, amelyeket az egyes pixelillesztők a platform saját formátumára alakítanak.

### Belső eseménynevek

| Belső esemény | Leírás |
|---|---|
| `page_view` | a felhasználó megnéz egy oldalt |
| `view_item` | a felhasználó megnéz egy terméket |
| `view_category` | a felhasználó megnéz egy termékkategóriát |
| `add_to_cart` | a felhasználó kosárba tesz egy terméket |
| `begin_checkout` | a felhasználó megkezdi a pénztárat |
| `add_payment_info` | a felhasználó megadja a fizetési adatokat |
| `purchase` | a vásárlás befejeződött |
| `add_to_wishlist` | a felhasználó kívánságlistára tesz egy terméket |
| `search` | a felhasználó keres |
| `login` | a felhasználó bejelentkezik |

### Platformonkénti eseménynevek

Minden pixelillesztő a belső eseménynevet a platform formátumára alakítja:

| Belső esemény | Facebook | TikTok | Snapchat | Pinterest |
|---|---|---|---|---|
| `page_view` | `PageView` | nincs | `PAGE_VIEW` | nincs |
| `view_item` | `ViewContent` | `ViewContent` | `VIEW_CONTENT` | `pagevisit` |
| `add_to_cart` | `AddToCart` | `AddToCart` | `ADD_CART` | `addtocart` |
| `purchase` | `Purchase` | `Purchase` | `PURCHASE` | `checkout` |

Ahol „nincs” áll, az illesztő nem támogatja az eseményt (nullát ad vissza, és az esemény arra a pixelre kimarad).

### Platformspecifikus adatok módosítása

A `pmw_pixel_data_{pixel}` szűrőkkel a platform formátumára alakítás utáni adatot módosíthatod:

```js
window._pmwq.push(function () {
    pmw.hooks.addFilter('pmw_pixel_data_facebook', 'my-plugin', function (pixelData, eventName) {
        if (eventName === 'add_to_cart') {
            pixelData.custom_data.source = 'mobile_app';
        }
        return pixelData;
    });
});
```
