--- phase: 05-purchase-redirect-hardening plan: 01 subsystem: analytics tags: [purchase, dataLayer, consent-mode-v2, przelewy24, redirect] requires: - phase: 02-purchase-event-prepayment provides: purchase event emitted before payment redirect - phase: 03-cookie-consent provides: CookieNoticePro and Consent Mode v2 integration - phase: 04-cookie-notice-bugfix provides: stable CookieNoticePro initialization provides: - Browser-session guard against duplicate purchase pushes per transaction_id - Saved cookie consent restore before GTM and purchase event execution - Centered Przelewy24 redirect alert with 5-second countdown and automatic submit affects: [analytics, checkout, payments] tech-stack: added: [] patterns: [sessionStorage duplicate guard, pre-GTM consent restore, delayed payment redirect] key-files: created: [] modified: - templates/tickets/przelewy24.php - templates/site/layout-logged.php key-decisions: - "Use `sessionStorage` keyed by transaction_id to prevent duplicate purchase on refresh." - "Restore saved CookieNoticePro consent before GTM starts, so purchase uses the right consent state." - "Use a centered Bootstrap alert and automatic submit after 5 seconds, without a visible fallback button." patterns-established: - "Purchase event may be emitted before payment redirect, but must be guarded per transaction in the browser session." duration: 35min started: 2026-05-08T00:00:00Z completed: 2026-05-08T00:00:00Z --- # Phase 5 Plan 01: Purchase Redirect Hardening Summary **Purchase tracking now fires once per transaction in the browser session, respects restored cookie consent before GTM, and redirects to Przelewy24 after a centered 5-second countdown alert.** ## Performance | Metric | Value | |--------|-------| | Duration | ~35 min | | Started | 2026-05-08 | | Completed | 2026-05-08 | | Tasks | 3 completed | | Files modified | 2 source files + PAUL docs | ## Acceptance Criteria Results | Criterion | Status | Notes | |-----------|--------|-------| | AC-1: Purchase fires only once per browser session and transaction | Pass | First load pushes ecommerce reset and purchase when no session key exists. | | AC-2: Refresh does not duplicate purchase | Pass | `sessionStorage` key `brzezovka_purchase_sent_{transaction_id}` suppresses repeat push in the same browser session. | | AC-3: Auto redirect returns with visible countdown | Pass | Centered Bootstrap alert shows 5-second countdown and auto-submits the P24 form after 5 seconds. | | AC-4: Saved cookie consent is restored before GTM and purchase | Pass | Layout restores `cnp_consent` and `cnp_prefs` immediately after default denied and before GTM. | ## Accomplishments - Added a guarded `dataLayer.push()` wrapper around the existing purchase payload. - Preserved the backend purchase payload builder and payment form signing unchanged. - Added pre-GTM saved consent restore for analytics and marketing consent. - Replaced the temporary manual redirect with a centered alert and automatic 5-second redirect. ## Verification Results | Check | Result | |-------|--------| | `php -l templates/tickets/przelewy24.php` | Pass | | `php -l templates/site/layout-logged.php` | Pass | | `rg -n "sessionStorage|brzezovka_purchase_sent_|redirectCountdown|setTimeout|cnp_consent|cnp_prefs" ...` | Pass | | Manual browser check: first purchase fires | Pass - confirmed by user during testing | | Manual browser check: saved consent restored | Pass - confirmed by user after consent fix | | Manual browser check: centered alert without visible button | Pass - user approved after visual correction | ## Files Created/Modified | File | Change | Purpose | |------|--------|---------| | `templates/tickets/przelewy24.php` | Modified | Added purchase duplicate guard, centered redirect alert, 5-second countdown, and auto-submit. | | `templates/site/layout-logged.php` | Modified | Restores saved CookieNoticePro consent before GTM snippet and page-level purchase push. | | `.paul/phases/05-purchase-redirect-hardening/05-01-PLAN.md` | Created | Plan for the hardening work. | | `.paul/phases/05-purchase-redirect-hardening/05-01-SUMMARY.md` | Created | Completion record. | | `.paul/STATE.md` | Modified | Tracks v0.4 loop closure. | | `.paul/ROADMAP.md` | Modified | Adds and closes Phase 5. | | `.paul/PROJECT.md` | Modified | Marks v0.4 requirements and decisions as validated. | | `.paul/changelog/2026-05-08.md` | Modified | Human-readable changelog entry. | ## Decisions Made | Decision | Rationale | Impact | |----------|-----------|--------| | Use sessionStorage instead of DB state | Scope was refresh protection in the same browser session, not a server-side analytics ledger. | No schema or order-flow changes required. | | Set session key before pushing purchase | Prevents duplicate push if refresh happens immediately after the first page execution. | Slight fail-open behavior remains if storage is unavailable. | | Restore consent before GTM | CookieNoticePro runs at the bottom of the body, too late for the pre-payment purchase push. | Purchase observes saved granted consent on page load. | | Remove visible manual button | User feedback: the button remained visible and the message needed a cleaner UI. | Final redirect page is a centered alert with no visible fallback button. | ## Deviations from Plan ### Summary | Type | Count | Impact | |------|-------|--------| | User-requested UI adjustment | 1 | Removed visible fallback button and improved message presentation. | **Total impact:** Positive UI cleanup; no tracking or payment behavior risk introduced. ## Issues Encountered | Issue | Resolution | |-------|------------| | Purchase initially used default denied consent despite saved cookie acceptance. | Added pre-GTM saved consent restore in `layout-logged.php`. | | Temporary redirect button was still visible and the text looked unpolished. | Replaced it with a centered Bootstrap alert and countdown only. | ## Next Phase Readiness **Ready:** - v0.4 tracking redirect hardening is complete. - Purchase event has refresh protection and consent ordering fixed. - Przelewy24 auto-redirect behavior is restored. **Concerns:** - `sessionStorage` protects only the same browser session; cross-device or new-session duplication would need server-side tracking if required later. **Blockers:** - None. --- *Phase: 05-purchase-redirect-hardening, Plan: 01* *Completed: 2026-05-08*