Files
bilety.brzezovka.pl/.paul/phases/02-purchase-event-prepayment/02-01-PLAN.md
Jacek Pyziak 86e712ba4f feat(02-purchase-event-prepayment): move purchase event to przelewy24 pre-payment page
Phase 2 complete:
- buildPurchaseDataLayer() called in przelewy24() controller, payload passed to template
- dataLayer.push added to templates/tickets/przelewy24.php (fires at order commitment)
- dataLayer.push removed from templates/tickets/order-confirm.php
- Captures 100% of orders regardless of user returning from payment gateway

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 22:29:54 +02:00

6.3 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, delegation
phase plan type wave depends_on files_modified autonomous delegation
02-purchase-event-prepayment 01 execute 1
autoload/controls/class.Tickets.php
templates/tickets/przelewy24.php
templates/tickets/order-confirm.php
true off
## Goal Przenieść event purchase dataLayer z order-confirm (po płatności) na stronę przelewy24 (po złożeniu zamówienia w DB, przed przekierowaniem do bramki płatniczej).

Purpose

Event purchase powinien rejestrować moment złożenia zamówienia, a nie powrotu z bramki. Użytkownicy, którzy nie wracają na stronę potwierdzenia po zapłacie, nie są teraz trackingowani. Przesunięcie na przelewy24 zapewnia pełne pokrycie analityczne.

GA4 + GTM używa navigator.sendBeacon() do wysyłania hitów — event dotrze do GA4 mimo że strona od razu przekierowuje na Przelewy24.

Output

  • autoload/controls/class.Tickets.php — buildPurchaseDataLayer() wywoływane w przelewy24(), nie w order_confirm()
  • templates/tickets/przelewy24.php — dodany blok dataLayer.push z payloadem purchase
  • templates/tickets/order-confirm.php — usunięty blok dataLayer.push purchase
## Project Context @.paul/PROJECT.md @.paul/ROADMAP.md @.paul/STATE.md

Prior Work

@.paul/phases/01-purchase-data-layer/01-01-SUMMARY.md

Source Files

@autoload/controls/class.Tickets.php @templates/tickets/przelewy24.php @templates/tickets/order-confirm.php

<acceptance_criteria>

AC-1: Purchase Event na stronie przelewy24

Given użytkownik złożył zamówienie i jest przekierowywany na /tickets/przelewy24/order=HASH
When strona przelewy24 się renderuje
Then window.dataLayer otrzymuje push eventu purchase z pełnym payloadem (transaction_id, value, currency, items)

AC-2: Brak Purchase Event na order-confirm

Given użytkownik wraca na /tickets/order_confirm/order=HASH po płatności
When strona order-confirm się renderuje
Then window.dataLayer NIE otrzymuje push eventu purchase

AC-3: Payload zawiera dane zamówienia

Given event purchase fires na przelewy24
When inspektujemy push w dataLayer
Then payload zawiera: event='purchase', ecommerce.transaction_id (id zamówienia), ecommerce.value (cena), ecommerce.currency='PLN', ecommerce.items (tablica biletów z item_id, item_name, quantity, price)

</acceptance_criteria>

Task 1: Przenieś buildPurchaseDataLayer() z order_confirm() do przelewy24() autoload/controls/class.Tickets.php W metodzie `przelewy24()`: - Po pobraniu `$order` (linia ~571), dodaj: `$purchaseDataLayer = self::buildPurchaseDataLayer($order);` - W wywołaniu `Tpl::view('tickets/przelewy24', [...])` dodaj klucz: `'purchase_data_layer' => $purchaseDataLayer`
W metodzie `order_confirm()`:
- Usuń linię `$purchaseDataLayer = self::buildPurchaseDataLayer($order);` (obecna tylko gdy payment_status == 1)
- W wywołaniu `Tpl::view('tickets/order-confirm', [...])` zmień `'purchase_data_layer' => $purchaseDataLayer` na `'purchase_data_layer' => null`
- Możesz też usunąć zmienną `$purchaseDataLayer = null;` z góry metody order_confirm()

Nie zmieniaj logiki `buildPurchaseDataLayer()` — tylko przenosimy gdzie jest wywoływana.
php -l "autoload/controls/class.Tickets.php" AC-1, AC-2: Kontroler przekazuje payload purchase do przelewy24 i null do order-confirm Task 2: Dodaj purchase push do przelewy24.php, usuń z order-confirm.php templates/tickets/przelewy24.php, templates/tickets/order-confirm.php W `templates/tickets/przelewy24.php`: - Na samym początku pliku (przed istniejącym PHP i HTML), dodaj identyczny blok dataLayer push jak był w order-confirm.php: ```php <?php $purchaseDataLayerJson = null; if (is_array($this->purchase_data_layer ?? null)) { $purchaseDataLayerJson = json_encode( $this->purchase_data_layer, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_INVALID_UTF8_SUBSTITUTE ); } ?> <?php if($purchaseDataLayerJson) : ?> <script type="text/javascript"> window.dataLayer = window.dataLayer || []; window.dataLayer.push({ ecommerce: null }); window.dataLayer.push(); </script> <?php endif; ?> ```
W `templates/tickets/order-confirm.php`:
- Usuń blok PHP + script na liniach 1-17 (cały blok $purchaseDataLayerJson + conditional script tag z dataLayer.push)
- Pozostałe treści (alerty $order_successful, $order_fail, dane zamówienia) pozostaw bez zmian.
- Sprawdź czy przelewy24.php zaczyna się od bloku PHP z $purchaseDataLayerJson - Sprawdź czy order-confirm.php NIE zawiera "purchaseDataLayerJson" ani "dataLayer.push({ ecommerce: null })" AC-1, AC-2, AC-3: Event fires na przelewy24, nie fires na order-confirm

DO NOT CHANGE

  • Logika metody buildPurchaseDataLayer() — tylko przeniesienie wywołania
  • Logika wysyłania emaili w przelewy24() i order_confirm()
  • Flaga informed_user i logika emaili w order_confirm()
  • templates/site/layout-logged.php — to jest zakres Phase 3
  • libraries/* — to jest zakres Phase 3
  • Inne szablony i kontrolery poza wymienionymi

SCOPE LIMITS

  • Nie dodawaj deduplicacji eventu (np. sesja/cookie blokująca ponowne wyemitowanie)
  • Nie zmieniaj struktury payloadu GA4 (pola event, ecommerce, order)
  • Nie modyfikuj przelewy24_response() ani innych akcji kontrolera
Before declaring plan complete: - [ ] php -l autoload/controls/class.Tickets.php — brak błędów składniowych - [ ] templates/tickets/przelewy24.php zawiera blok $purchaseDataLayerJson i window.dataLayer.push - [ ] templates/tickets/order-confirm.php NIE zawiera purchaseDataLayerJson ani dataLayer.push({ ecommerce: null }) - [ ] Wszystkie acceptance criteria spełnione

<success_criteria>

  • Oba zadania wykonane
  • PHP syntax valid
  • Event purchase fires na stronie przelewy24 z pełnym payloadem
  • Brak eventu purchase na stronie order-confirm </success_criteria>
After completion, create `.paul/phases/02-purchase-event-prepayment/02-01-SUMMARY.md`