# Recept: státuszvezérelt vásárlási konverziók

> A vásárlási konverzió rögzítése csak akkor, ha a WooCommerce kifizetett állapotot jelez: Conversions API mint egyetlen forrás, szigorúbb kifizetettség-definíció, egyedi státuszok.

Ez a recept a Facebook (és más platformok) vásárlási konverzióját csak akkor rögzíti, ha a WooCommerce megerősíti, hogy a rendelés kifizetett állapotban van, a platform Conversions API-ját használva egyetlen igazságforrásként.

## Mikor van szükséged erre a receptre?

A WooCommerce-rendelések a pénztár után három nagy kimenetelre oszlanak:

1. **A rendelés azonnal meghiúsul.** A vásárló sosem ér el a megköszönő oldalra. Semmi nem sül el, nincs teendő.
2. **A rendelés azonnal kifizetett** (a legtöbb Stripe- vagy PayPal-szerű integráció). A böngészőpixel a megköszönő oldalon, a CAPI a kifizetett státuszra váltáskor sül el, mindkettő ugyanazt az `event_id` értéket használja, és a Meta kettőzésmentesíti őket. Ez a normál eset, nincs teendő.
3. **A rendelés `feldolgozás alatt` (processing) állapotba kerül, de még meghiúsulhat vagy sosem fizetik ki** (banki átutalás, számla, részletfizetés, kézi ellenőrzés). A böngészőpixel a megköszönő oldalon elsül és rögzíti a konverziót, akkor is, ha a rendelést később lemondják vagy sosem fizetik ki.

Ez a recept a 3. esetre szól.

A Pixel Manager alapértelmezett működése mindent követ, ami nem hiúsul meg azonnal, mert a legtöbb pénztár a 2. esetbe esik, és a kifizetett státuszra várás a gyakori esetben rontja az attribúciót és a Meta optimalizálóját. Csak akkor használd ezt a receptet, ha a 3. eset annyira gyakori a boltodban, hogy torzítja a számokat.

### Mi a CAPI, és mi nem

A Conversions API a követés megbízhatóságára készült: az eseményeket a szerverről közvetlenül a Metának küldi, hogy túlélje a hirdetésblokkolókat, a böngészők adatvédelmi szabályait és a böngészőpixelt elnyomó hálózati szűrőket. A szokásos beállításban a CAPI a böngészőpixel mellett tartalékként fut, és a Meta az `event_id` alapján kettőzésmentesíti a kettőt. Ez a recept a CAPI-t a vásárlási események egyetlen küldőjévé teszi, hogy kihasználja a beépített, státuszvezérelt kiváltóját.

### A 7 napos korlát

A Meta Conversions API csak olyan eseményt fogad el, amelynek `event_time` értéke az elmúlt 7 napon belül van. Ha egy rendelés 7 napnál tovább marad `feldolgozás alatt` állapotban, mielőtt kifizetett státuszra vált, a konverziója véglegesen elvész. Ez a Meta oldalán kemény korlát.

## Hogyan kezeli a Pixel Manager alapból a vásárlási eseményeket

A Facebooknál a Pixel Manager a vásárlási eseményt két helyről sütti el:

1. **Böngészőpixel:** a rendelés-megerősítő (megköszönő) oldalon sül el, a rendelés fizetési státuszától függetlenül.
2. **Conversion API (CAPI):** az alább felsorolt rendelési státuszváltásokra regisztrált. A rendelésen egy meta-kulcsos őr megakadályozza a dupla elsülést ezek között a hookok között.

Mindkét esemény ugyanazt az `event_id` értéket kapja (`pmw_{rendelés azonosítója}`), a Facebook ezen kettőzésmentesít.

### Mely váltások váltják ki a szerveroldali vásárlást

A szerveroldali vásárlási esemény ezekre van regisztrálva:

- `woocommerce_payment_complete`
- minden `woocommerce_order_status_{kifizetett státusz}` váltás, ahol a kifizetett státuszokat a `wc_get_is_paid_statuses()` adja, alapból `processing` és `completed`
- `woocommerce_order_status_on-hold`

> **A szerveroldali vásárlás státuszvezérelt, de a „státuszvezérelt” nem azonos a „kifizetettel”.** Két eset eljut a hirdetési platformokhoz, bár pénz nem érkezett:
>
> - **Függőben (on-hold) lévő rendelések.** Az `on-hold` állapotba lépés szándékos kiváltó. Azok a fizetési módok, amelyek a rendelést fizetésre várva parkoltatják (kriptoszámlák, banki átutalás, egyes részletfizetési megoldások), különben napokkal későn jelentenék a konverziókat, a Meta pedig bünteti a késő jelentést. Egy olyan boltban, ahol a legtöbb függő rendelést sosem fizetik ki, ez felfújja a konverziók számát.
> - **Nulla értékű rendelések.** Az ingyenes rendelés (nulla forintos próbaelőfizetés, ingyenes csomag, teljesen kedvezményezett kosár) a `payment_complete()` függvényen át kifizetett státuszba kerül, ezért mint bármely más rendelés, vásárlást vált ki. Ezen az úton semmi nem vizsgálja a rendelés végösszegét.
>
> A meghiúsult, lemondott és visszatérített rendelések soha nem váltanak ki szerveroldali vásárlást. A `pending` (függőben lévő fizetés) státuszú rendelések sem, mert arra nem fut hook, de az a rendelés, amely röviden áthaladt az `on-hold` állapoton, mielőtt a fizetési mód visszaállította, útközben kiváltott egyet.
>
> Ha bármelyik eset érint, a szerveroldali vásárlást kapuzd a lent leírt `pmw_skip_s2s_purchase_event` szűrővel. A nem kifizetett rendeléseket nem csak a böngészőpixel rögzíti.

## A recept

Ha a konverziókat szigorúan akkor akarod rögzíteni, amikor a rendelés kifizetett állapotba ér, két dolgot kell tenned:

### 1. Kapcsold be a Facebook CAPI-t

A Pixel Managerben nyisd meg a **Tracking Pixels → Meta** részt, és kapcsold be a **Conversions API** beállítást. Ez teszi a CAPI-t azzá a forrássá, amely a vásárlási eseményt a Metának eljuttatja.

A Facebook bekapcsolása a Pixel Managerben a Meta for WooCommerce bővítmény követőpixelét is kikapcsolja, ha az telepítve van. A termékkatalógus-szinkront a Meta for WooCommerce-ből ez nem érinti.

### 2. Nyomd el a Facebook böngészőpixelt a vásárlási eseményeknél

Adj hozzá egy JavaScript-szűrőt, amely a Facebook-pixel `purchase` eseményeire `null` értéket ad vissza. A `pmw_pixel_data_{pixel}` szűrőből visszaadott `null` megakadályozza, hogy az adott pixel elsüljön az illeszkedő eseményre.

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-store/status-driven-purchase',
                function (pixelData, eventName) {
                    if (eventName === 'purchase') {
                        return null;
                    }
                    return pixelData;
                }
            );
        });
    </script>
    <?php
}, 1);
```

Az elnyomott böngészős vásárlási eseménnyel a CAPI az egyetlen küldő, a kettőzésmentesítés megszűnik, és a konverziók akkor jelennek meg a Metában, amikor a WooCommerce a rendelést kifizetett állapotba teszi. A legtöbb fizetési módnál ez gyakorlatilag azonnali. Offline vagy kézzel jóváhagyott fizetésnél a konverzió abban a pillanatban rögzül, amikor a rendelés kifizetett státuszra vált.

## Szigorúbb „kifizetett” definíció (szerveroldali szűrő)

Akkor használd, ha a fenti kiváltólista tágabb, mint a te konverziódefiníciód: ki akarod zárni a függő (on-hold) rendeléseket, a nulla értékű rendeléseket, vagy a `processing` rendeléseket egy olyan boltban, amely csak a `completed` rendeléseket számolja.

A használandó szűrő a `pmw_skip_s2s_purchase_event` (lásd: [Szerveroldali szűrők](https://hub.hellowp.io/hu/plugins/woocommerce-pixel-manager/fejlesztoknek-php-szurok-szerveroldal/)). Maga a rendelést kapja, és a `true` visszaadása minden platformra elnyomja a szerveroldali vásárlást, a SweetCode Cloud proxy útvonalat is, és a rendelést kizárja a Google Ads konverziómódosítási adatforrásból is.

```php
add_filter('pmw_skip_s2s_purchase_event', function ($skip, $order) {
    if (!$order instanceof WC_Order) {
        return $skip;
    }

    // Nulla értékű rendelés ne számítson
    if ((float) $order->get_total() <= 0) {
        return true;
    }

    // Csak kifizetett rendelés számítson
    if (!$order->is_paid()) {
        return true;
    }

    return $skip;
}, 10, 2);
```

A kihagyott rendelést a bővítmény nem jelöli elküldöttnek, ezért a vásárlás normálisan kimegy abban a pillanatban, amikor a rendelés ténylegesen eléri a kifizetett státuszt. Ettől lesz a szűrő kapu, nem végleges kizárás.

A definíció tovább szűkítéséhez, például csak a `completed` státuszra, cseréld le az `is_paid()` ellenőrzést:

```php
if ($order->get_status() !== 'completed') {
    return true;
}
```

Ha a szabályt csak egy platformra akarod alkalmazni, olvasd a szűrő harmadik argumentumát, amely a pixelosztály nevét hordozza:

```php
use SweetCode\Pixel_Manager\Pixels\Facebook\Facebook_CAPI;

add_filter('pmw_skip_s2s_purchase_event', function ($skip, $order, $context) {
    if ($context !== Facebook_CAPI::class) {
        return $skip;
    }
    return ($order instanceof WC_Order && !$order->is_paid()) ? true : $skip;
}, 10, 3);
```

> **Ehhez ne használd a `pmw_server_event_payload_{pixel}_purchase` szűrőt.** Az [Eseményszűrők](https://hub.hellowp.io/hu/plugins/woocommerce-pixel-manager/fejlesztoknek-esemenyszurok/) fejezetben leírt `pmw_server_event_payload_*` szűrők a szerverre továbbított böngészőeseményeken futnak. A láncot tápláló végpont elutasítja a `purchase` eseményeket, mert a vásárlást mindig a szerveren állítja össze a rendelésből, és sosem fogadja el a böngészőtől. A `pmw_server_event_payload_facebook_purchase` szűrőre írt visszahívás ezért soha nem fut le, és az arra épített státuszkapu csendben hibázik. Az egyetlen kivétel a Google Analytics 4: a Measurement Protocol a `pmw_server_event_payload_google_analytics`, `pmw_server_event_payload_google_analytics_purchase` és `pmw_server_event_payload_post` szűrőket a saját vásárlási adatcsomagjára alkalmazza, így ez a három GA4-re lefut. Minden más platformra használd a `pmw_skip_s2s_purchase_event` szűrőt.

A régebbi változatokon a szerveroldali vásárlási út a Pixel Manager belső rendelésobjektumát adta át ennek a szűrőnek a `WC_Order` helyett, ezért a fenti `instanceof WC_Order` őr csendben kihagyta az egész visszahívást. Frissíts egy újabb változatra, ahol a szűrő ismét a WooCommerce-rendelést kapja. Ha régebbi változatot is támogatnod kell, előbb old fel az argumentumot: `$order = wc_get_order(is_object($order) ? $order->get_id() : $order);`.

## Egyedi rendelési státuszok (például `partially-paid`)

A foglaló- és részfizetési bővítmények egyedi rendelési státuszokat adnak hozzá, amelyeket a WooCommerce nem kezel kifizetettként. Mivel a vásárlási konverzió a kifizetett státuszba lépéskor sül el, az a rendelés, amely csak egy egyedi státuszba (például `partially-paid`) jut el, soha nem vált ki vásárlási konverziókövetést.

Egyedi rendelési státusz kifizetettként való regisztrálására használd a WooCommerce `woocommerce_order_is_paid_statuses` szűrőjét. Ez a `wc_get_is_paid_statuses()` mögötti szűrő, ezért a Pixel Manager automatikusan felveszi, és elsüti a vásárlási konverziót, amikor a rendelés ebbe a státuszba lép:

```php
add_filter('woocommerce_order_is_paid_statuses', function ($statuses) {
    $statuses[] = 'partially-paid';
    return $statuses;
});
```

Ehhez nincs külön Pixel Manager-szűrő: a WooCommerce szűrője az egyetlen igazságforrás. Vedd figyelembe, hogy ez kiszélesíti azt, amit maga a WooCommerce kifizetettnek tekint (például az `$order->is_paid()` eredményét), nem csak a Pixel Manager konverziókiváltóját.

## Nem kötelező: a CAPI kézi újraküldése egy rendelésre

Ha egy egyedi munkafolyamatnak egy adott rendelésre CAPI vásárlási eseményt kell küldenie (például egy egyedi hookból), hívd meg a platform statikus `send_purchase_hit()` metódusát a rendelésobjektummal:

```php
\SweetCode\Pixel_Manager\Pixels\Facebook\Facebook_CAPI::send_purchase_hit($order);
```

Ez belső metódus, és nem része a Pixel Manager nyilvános API-jának. Kiadások között változhat.

## Ugyanez a minta más platformokra

Ugyanez a megközelítés minden olyan platformra működik, amelynek van szerveroldali megfelelője a Pixel Managerben. Csak a JavaScript-szűrő neve változik platformonként, mert a szerveroldali kapu mindegyiknél ugyanaz az egy szűrő.

| Platform | JavaScript-szűrő | Szerveroldali kapu |
|---|---|---|
| Facebook / Meta | `pmw_pixel_data_facebook` | `pmw_skip_s2s_purchase_event`, a `$context` értéke `Facebook_CAPI::class` |
| TikTok | `pmw_pixel_data_tiktok` | `pmw_skip_s2s_purchase_event`, a `$context` értéke `TikTok_EAPI::class` |
| Pinterest | `pmw_pixel_data_pinterest` | `pmw_skip_s2s_purchase_event`, a `$context` értéke `Pinterest_APIC::class` |
| Snapchat | `pmw_pixel_data_snapchat` | `pmw_skip_s2s_purchase_event`, a `$context` értéke `Snapchat_CAPI::class` |
| Reddit | `pmw_pixel_data_reddit` | `pmw_skip_s2s_purchase_event`, a `$context` értéke `Reddit_CAPI::class` |
| Google Analytics 4 | `pmw_pixel_data_google_analytics` | `pmw_skip_s2s_purchase_event`, a `$context` értéke `Google_MP_GA4::class` |

A Microsoft Advertising, a Nextdoor, a Mixpanel, az OpenAI és a többi szerveroldali platform ugyanezzel a szűrővel kapuzható, a pixelosztályaik a `SweetCode\Pixel_Manager\Pixels\{Platform}` névtérben vannak. Ha kihagyod a `$context` ellenőrzést, az összes platformot egyszerre kapuzod, ahogy a fenti példa is teszi.

A Google Analytics 4 emellett kínálja a `pmw_server_event_payload_google_analytics_purchase` szűrőt a Measurement Protocol adatcsomag módosítására. Ezt arra használd, hogy megváltoztasd, mi megy ki, nem arra, hogy eldöntsd, kimegy-e egyáltalán: a kihagyó szűrő korábban fut, és olcsóbb kapu, mert a kihagyott rendeléshez sosem épül adatcsomag.

## Platformok szerveroldali megfelelő nélkül (Google Ads és mások)

Ez a recept azon alapul, hogy a platformnak van szerveroldali vásárlási API-ja a Pixel Managerben, mert az adja a státuszvezérelt kiváltót. A Google Adsnek nincs, és a LinkedInnek, az X-nek, a Taboolának, az Outbrainnek, az AdRollnak, a Criteónak és a többi, csak böngészős pixelnek sincs. Ezeknél a vásárlási konverzió a böngészőből megy, ezért a böngészős esemény elnyomása szerveroldali küldő nélkül teljesen eldobja a konverziót.

A Microsoft Advertising korábban ezen a listán volt. A Pro változatban már van Conversions API-ja, ezért a fenti receptet követi.

Ezekhez használd a `pmw_conversion_prevention` PHP-szűrőt (lásd: [Szerveroldali szűrők](https://hub.hellowp.io/hu/plugins/woocommerce-pixel-manager/fejlesztoknek-php-szurok-szerveroldal/)). Egy adott rendelésnél visszatartja a böngészős vásárlási konverziót, amíg a rendelés nem kifizetett státuszú, és mivel a szűrőt az [Automatic Conversion Recovery](https://hub.hellowp.io/hu/plugins/woocommerce-pixel-manager/funkciok-acr/) (Pro) újra kiértékeli, a konverzió teljes egészében visszaszerződik a vásárló következő látogatásakor, miután a rendelést kifizették.

Két különbséget érdemes tudnod a CAPI-alapú recepthez képest, mielőtt ezt választod:

- Az érintett rendeléseknél minden böngészős vásárlási pixelt elnyom, nem csak egy platformot, mert a rendelés adatait az adatrétegből teljes egészében visszatartja.
- A helyreállításhoz a vásárlónak ugyanazzal a böngészővel vissza kell térnie a boltba. A CAPI-nak nincs szüksége visszatérő látogatásra.

Ha a beállításodban egy platformnak van Conversion API-ja, azon a platformon ezt a receptet részesítsd előnyben, a szűrőt pedig csak a csak böngészős pixelekre használd.

## Hibaelhárítás

- **A konverziók még mindig megjelennek a meghiúsult rendeléseknél.** A böngészőpixel-szűrő nincs aktív. Ellenőrizd, hogy a kódrészlet kikerül az oldal forrására, és hogy a `pmw.hooks` definiált, amikor lefut (ezt garantálja a `_pmwq` parancssor).
- **Egyáltalán nem jelennek meg konverziók.** Ellenőrizd, hogy a Facebook CAPI be van-e kapcsolva a Pixel Managerben a **Tracking Pixels → Meta** alatt, és hogy a hozzáférési token érvényes-e. A CAPI-kérést a Pixel Manager **Support → Logger** részén kapcsolt naplókban keresd.
- **A konverziók később jelennek meg, mint vártad.** Ez a várt működés. A CAPI akkor sül el, amikor a WooCommerce a rendelést kifizetett státuszba teszi, nem amikor a vásárló a megköszönő oldalra ér.
- **A böngészőpixel elnyomása után is megjelennek konverziók függő (on-hold), nem kifizetett vagy ingyenes rendeléseknél.** Ezek a szerveroldali eseményből jönnek, amely az `on-hold` állapotba lépéskor is elsül, és nem ellenőrzi a rendelés végösszegét. Add hozzá a `pmw_skip_s2s_purchase_event` kaput. Ha már hozzáadtad, és semmi nem változott, ellenőrizd két dolgot: hogy a visszahívásod a `pmw_skip_s2s_purchase_event` szűrőre van-e regisztrálva, és nem a `pmw_server_event_payload_{pixel}_purchase` szűrőre, amely vásárlásra soha nem fut le, valamint hogy a bővítményed elég friss-e, mert a régebbi változatok rossz objektumot adtak át a visszahívásnak.
- **Több vásárlási esemény van, mint kifizetett rendelés a platform eseménykezelőjében.** Hasonlítsd össze a mögöttük álló rendelésazonosítókat. Az eseményazonosító `pmw_{rendelés azonosítója}`, így egy szúrópróba a rendelés státuszelőzményével általában kimutat egy függő (on-hold) váltást, egy ingyenes rendelést vagy egy olyan rendelést, amely röviden áthaladt az `on-hold` állapoton, mielőtt a fizetési mód visszaállította `pending` állapotra.

Kapcsolódó fejezetek: [Eseményszűrők](https://hub.hellowp.io/hu/plugins/woocommerce-pixel-manager/fejlesztoknek-esemenyszurok/), [PHP-szűrők](https://hub.hellowp.io/hu/plugins/woocommerce-pixel-manager/fejlesztoknek-php-szurok-ertekek/).
