Treści i cele przycisków w aplikacji mobilnej
Sloty treści marketingowych, obiekt link (type, params, url), pomiar pokazań paczką content/events, X-Device-Id i tryb gościa - ustalenia z zespołem aplikacji.
Zaktualizowano 2 listopada 2026
Na tej stronie
Banery, karuzela, aktualności i paski z wezwaniem do działania w aplikacji to te same treści co w portalu klienta. Marka przygotowuje je w panelu i przy każdej treści wybiera kanał: portal, aplikacja albo oba (Treści w portalu i aplikacji). Ten przewodnik opisuje, jak aplikacja je pobiera, dokąd prowadzi przycisk i jak zgłaszać pokazania. Zasady ustalono z zespołem aplikacji w listopadzie 2026 (decyzje A1-A6, tabela na końcu).
Pobieranie treści
API zwraca wyłącznie treści z kanałem „Aplikacja mobilna”, które działają w tej chwili dla widza: w swoim okresie
i harmonogramie, dla gościa, zalogowanego albo segmentu. Sekcja treści nie ma przełącznika - marka bez treści
daje puste sloty, a nie FEATURE_DISABLED.
| Slot | Miejsce | Ile treści |
|---|---|---|
portal_home_hero |
duży baner startu | 1 |
portal_home_banner |
karuzela startu | do 5 |
portal_home_news |
aktualności na starcie (wszystkie: GET news) |
3 |
portal_home_cta |
pasek z wezwaniem | 1 |
portal_offer_top |
nad ofertą | 1 |
portal_account |
pasek w „Moich danych”, tylko dla zalogowanych | 1 |
GET content/home zwraca cztery sloty startu jednym żądaniem, GET content?placement=... - jeden slot,
GET news/{uuid} - pełny wpis aktualności. Obrazy to oryginały: animowany GIF zostaje animacją (image.animated).
Pole image może być null - pokaż wtedy treść w barwach marki z brand/config.
Obiekt link
Przycisk treści (cta) ma label i link:
{
"type": "shop_product",
"params": { "uuid": "...", "category_uuid": "...", "localization_uuid": "..." },
"url": "https://...",
"deep_link": "shop/products/...",
"requires_login": false
}- Ekran wybieraj wyłącznie po
typeiparams. Nie parsujurlanideep_link.paramsjest zawsze obiektem; każdy cel z obiektem (offer_category,shop_category,shop_product,news_item) maparams.uuid. deep_linkto tylko informacyjna podpowiedź (np. do logów). Nie buduj z niego nawigacji.urljest zawsze https: ten sam cel w portalu klienta albo adres zewnętrzny, z parametrami UTM. To zapas dla ekranu, którego aplikacja jeszcze nie ma - otwórz go w przeglądarce w aplikacji. Linków uniwersalnych nie ma, bo każda marka ma własną domenę.requires_login = true- ekran konta. Gościa najpierw przeprowadź przez logowanie.- Brak
ctaoznacza treść bez przycisku albo cel, którego już nie ma (sekcja wyłączona, produkt usunięty).
type |
Ekran w aplikacji |
|---|---|
home, news, news_item |
start, aktualności, wpis aktualności |
shop, shop_category, shop_product |
sklep, kategoria, karta produktu |
rewards |
nagrody |
tickets, customer_code, my_rewards, orders, shop_orders, account |
ekrany konta - wymagają logowania |
login |
logowanie albo zakładanie konta |
offer, offer_category, help |
brak ekranu natywnego - otwórz url (strona działa bez logowania) |
url |
adres zewnętrzny - otwórz url w przeglądarce |
| nieznany (nowszy serwer) | otwórz url; gdy url jest pusty albo nie https - ukryj przycisk |
Oferta, kategoria oferty i pomoc w przeglądarce w aplikacji to stan tymczasowy. Docelowo dostaną ekrany
natywne (wytyczna Apple 4.2) - zmieni się wtedy tylko ekran w tabeli, obiekt link zostanie ten sam.
Pomiar pokazań i kliknięć
Pokazanie liczy się według standardu IAB: co najmniej połowa elementu widoczna przez co najmniej 1 sekundę.
Jedno pokazanie danej treści na jedno wejście na ekran - przewinięcie z powrotem nie jest nowym pokazaniem.
Slajd karuzeli przewijanej automatycznie liczy się tak samo. Otwarcie wpisu aktualności to pokazanie wpisu.
Dotknięcie przycisku albo karty aktualności to kliknięcie. Samo pobranie treści (GET) niczego nie liczy.
- Zbieraj zdarzenia w kolejce:
content_uuid,type(impressionalboclick),occurred_at(chwila zdarzenia, ISO 8601 ze strefą) i opcjonalnie własneid. - Co kilka sekund i przy przejściu aplikacji w tło wyślij
POST content/eventsz listąevents(do 100 zdarzeń). - Po odpowiedzi usuń z kolejki wszystkie wysłane zdarzenia - także
duplicateirejected. - Ponawiaj paczkę tylko po braku odpowiedzi, po 5xx albo po 429.
Wynik przychodzi dla każdego zdarzenia w kolejności paczki: counted, duplicate (już policzone w tej sesji,
dla tej treści, rodzaju i dnia) albo rejected z powodem (invalid_event, invalid_occurred_at,
occurred_in_future, too_old, content_not_found, content_not_live). Odrzucenie jest ostateczne.
422 VALIDATION_ERROR dotyczy tylko złej koperty: brak events, pusta lista albo ponad 100 elementów.
Okno czasu: occurred_at najwyżej 5 minut w przód i 24 godziny wstecz. Dzień zdarzenia liczy się w strefie
Europe/Warsaw. Ponowna wysyłka tej samej paczki jest bezpieczna - da duplicate. Idempotency-Key nie
jest tu potrzebny. Pojedyncze POST content/{uuid}/impression i click zostały dla zgodności; click zwraca
też bieżący link celu.
Sesja i X-Device-Id
Serwer liczy pokazanie raz na sesję aplikacji, treść, rodzaj i dzień. Sesją zalogowanego jest token. Sesją
gościa jest nagłówek X-Device-Id - losowy identyfikator instalacji (np. UUID v4); bez niego serwer używa
skrótu IP i przeglądarki.
X-Device-Id jest osobny od device_id z logowania. Serwer ich nie łączy i nie przenosi pokazań gościa na
konto: po zalogowaniu nagłówek jest pomijany, a ta sama treść liczy się w nowej sesji. Nie jest to
identyfikator reklamowy. Nie przechowuj go w iOS Keychain - Keychain przeżywa odinstalowanie aplikacji,
a identyfikator ma opisywać instalację.
Tryb gościa i powrót po logowaniu
Opis tekstowy diagramu
- Start bez logowania brand/config, content/home, news → Klient dotyka przycisku
- Klient dotyka przycisku → requires_login?
- requires_login? → Ekran celu (nie)
- requires_login? → Logowanie, cel zapamiętany (tak)
- Logowanie, cel zapamiętany → Cel dostępny?
- Cel dostępny? → Ekran celu (tak)
- Cel dostępny? → Start z komunikatem (nie)
- Logowanie, cel zapamiętany → Ponowne content/home
Cel jest niedostępny, gdy click zwrócił link: null albo ekran celu odpowiedział 404 lub FEATURE_DISABLED.
Po zalogowaniu pobierz content/home ponownie - z tokenem dochodzą treści dla zalogowanych i segmentu.
Ustalenia z zespołem aplikacji (A1-A6)
| Pytanie | Ustalenie | |
|---|---|---|
| A1 | Jak aplikacja wybiera ekran celu? | Wyłącznie po type + params; url i deep_link nie są do parsowania; linków uniwersalnych nie ma. |
| A2 | Co z ekranami bez API (oferta, kategoria oferty, pomoc)? | url w przeglądarce w aplikacji, bez sesji aplikacji - strony portalu działają bez logowania. Stan tymczasowy. |
| A3 | Czym jest identyfikator gościa? | X-Device-Id, losowy identyfikator instalacji, osobny od device_id logowania; bez łączenia z kontem. |
| A4 | Kiedy zgłaszać pokazanie? | IAB: połowa elementu przez 1 s, raz na wejście na ekran; paczka POST content/events co kilka sekund i przy przejściu w tło. |
| A5 | Co po logowaniu z przycisku requires_login? |
Aplikacja otwiera zapamiętany cel; cel niedostępny = powrót na start z komunikatem. |
| A6 | Co z nieznanym typem celu? | Otwórz url, tylko https; adres bez https = brak przycisku. |
Powiązane
- API aplikacji mobilnej klienta Marka w nagłówku, logowanie kodem i hasłem, konto, zgody i e-paragony, tryb gościa, sekcje marki, Idempotency-Key, punkty, nagrody, zamówienia, sklep, bilety i kod klienta w API aplikacji klienta.
- Treści w portalu i aplikacji Jak dodać baner, karuzelę, aktualność albo pasek z wezwaniem do działania w portalu klienta i aplikacji mobilnej marki - miejsca, kanały, cel przycisku, obrazy, odbiorcy, harmonogram i wyniki.
- Zmiany w API Historia wersji trzech interfejsów API (pole info.version w plikach OpenAPI) - co doszło w każdej wersji i na co zwrócić uwagę przy aktualizacji klienta.