Integracja z własną platformą (Custom)

Koszyk.pro pozwala na integrację z dowolną platformą e-commerce — nie musisz korzystać z Shoper ani Shopify. Wystarczy widget JavaScript, opcjonalne API do synchronizacji koszyków lub webhooki push. Poniżej znajdziesz szczegółową instrukcję konfiguracji.

Jak dodać sklep

Integracja Custom nie wymaga OAuth — wystarczy podać podstawowe dane sklepu. Wykonaj poniższe kroki:

  1. Zaloguj się do swojego konta w Koszyk.pro.
  2. Przejdź do sekcji „Sklepy" i kliknij przycisk „Dodaj sklep".
  3. Wybierz platformę Custom z listy dostępnych integracji.
  4. Podaj nazwę i adres URL swojego sklepu — nazwa jest dowolna (np. „Mój sklep"), a URL musi zaczynać się od https://.
  5. Gotowe! Sklep pojawi się na liście ze statusem „Aktywny". Otrzymasz token widgetu, który użyjesz do integracji JavaScript na swoich stronach.

Opcjonalnie możesz skonfigurować API do synchronizacji koszyków — szczegóły znajdziesz w sekcji poniżej.

Konfiguracja API koszyków

Jeśli Twoja platforma posiada API, z którego Koszyk.pro może cyklicznie pobierać koszyki (polling co 15 minut), skonfiguruj je w ustawieniach sklepu.

URL API koszyków

W panelu sklepu, w polu „URL API koszyków", podaj adres endpointu, który zwraca listę aktywnych koszyków w formacie JSON. Koszyk.pro będzie odpytywać ten endpoint z parametrem limit (domyślnie 50).

Akceptowane formaty odpowiedzi

Endpoint może zwracać dane w jednym z trzech formatów:

1. Tablica koszyków (bezpośrednio):

[
{ "id": "cart-001", "email": "klient@example.com", ... },
{ "id": "cart-002", "email": "inny@example.com", ... }
]

2. Obiekt z polem carts:

{
"carts": [
{ "id": "cart-001", "email": "klient@example.com", ... }
]
}

3. Obiekt z polem data:

{
"data": [
{ "id": "cart-001", "email": "klient@example.com", ... }
]
}

Pola koszyka

Każdy koszyk w odpowiedzi JSON może zawierać poniższe pola. Koszyk.pro akceptuje różne warianty nazw — wybierz te, które pasują do Twojego API:

Pole Akceptowane nazwy Wymagane Opis
ID koszyka platform_cart_id, id, cart_id, cartId Tak Unikalny identyfikator koszyka w Twoim systemie
Email klienta customer_email, email, customerEmail Tak Adres email klienta — niezbędny do wysyłki przypomnień
Imię klienta customer_name, name, customerName Nie Imię i nazwisko klienta
Wartość total_value, total, totalValue Nie Łączna wartość koszyka (np. "99.99")
Waluta currency Nie Kod waluty ISO 4217 (domyślnie "PLN")
Data utworzenia platform_created_at, created_at, createdAt Nie Data utworzenia koszyka w formacie ISO 8601 lub YYYY-MM-DD HH:MM:SS
Data aktualizacji platform_updated_at, updated_at, updatedAt, lastUpdated Nie Data ostatniej zmiany koszyka w formacie ISO 8601 lub YYYY-MM-DD HH:MM:SS. Zalecane — używane do filtrowania po parametrze since.
Produkty items Nie Lista produktów w koszyku (patrz tabela poniżej)

Pola produktu (items)

Każdy element w tablicy items może zawierać:

Pole Akceptowane nazwy Opis
ID produktu platform_product_id, id, product_id, productId Identyfikator produktu
Nazwa name, title Nazwa produktu
Cena unit_price, price, unitPrice Cena jednostkowa (np. "49.99")
Ilość quantity Ilość sztuk (domyślnie 1)
SKU sku Kod SKU produktu
Zdjęcie image_url, image, imageUrl URL zdjęcia produktu
Link product_url, url, productUrl URL strony produktu

Przykładowa odpowiedź API

Poniżej pełny przykład odpowiedzi z dwoma produktami, używający różnych wariantów nazw pól:

{
"carts": [
{
  "cart_id": "abc-123",
  "email": "jan.kowalski@example.com",
  "customer_name": "Jan Kowalski",
  "total": "149.98",
  "currency": "PLN",
  "created_at": "2026-03-08T10:30:00Z",
  "items": [
    {
      "product_id": "prod-001",
      "title": "Koszulka bawełniana",
      "price": "49.99",
      "quantity": 2,
      "sku": "KB-001-M",
      "image": "https://sklep.pl/img/koszulka.jpg",
      "url": "https://sklep.pl/koszulka-bawelniana"
    },
    {
      "id": "prod-002",
      "name": "Czapka zimowa",
      "unit_price": "49.99",
      "quantity": 1,
      "sku": "CZ-002",
      "image_url": "https://sklep.pl/img/czapka.jpg",
      "product_url": "https://sklep.pl/czapka-zimowa"
    }
  ]
}
]
}

Autoryzacja

Koszyk.pro obsługuje dwa sposoby autoryzacji zapytań do Twojego API:

  • Bearer token — nagłówek Authorization: Bearer TWOJ_TOKEN. Wybierz typ autoryzacji „Bearer" i podaj token w konfiguracji sklepu.
  • Niestandardowy nagłówek — np. X-API-Key: TWOJ_KLUCZ. Wybierz typ autoryzacji „Nagłówek", podaj nazwę nagłówka (np. X-API-Key) i jego wartość.

Jeśli Twoje API nie wymaga autoryzacji, pozostaw te pola puste.

Filtrowanie po dacie (parametr since)

Koszyk.pro przy każdej synchronizacji wysyła parametr since z datą ostatniej udanej synchronizacji w formacie ISO 8601. Twoje API powinno zwracać tylko koszyki zaktualizowane po tej dacie:

GET /api/carts?limit=100&since=2026-03-20T10:00:00Z

Dzięki temu przy każdym cyklu synchronizacji (co 15 minut) pobierane są tylko nowe lub zmienione koszyki — nie wszystkie od początku. Jeśli Twoje API nie obsługuje parametru since, Koszyk.pro pobierze wszystkie koszyki do limitu — ale zalecamy implementację tego parametru dla sklepów z dużą liczbą koszyków.

Paginacja

Jeśli Twoje API zwraca wiele koszyków, możesz podzielić odpowiedź na strony. Koszyk.pro automatycznie pobierze kolejne strony (max 10 stron na synchronizację). Obsługiwane są dwa formaty:

1. Kursor (zalecany):

      {
    "carts": [... ],
    "next_cursor": "eyJpZCI6MTAwfQ=="
  }

Gdy odpowiedź zawiera pole next_cursor, Koszyk.pro wykona kolejne zapytanie z parametrem ?cursor=eyJpZCI6MTAwfQ==. Jeśli ostatnia strona nie zawiera next_cursor, paginacja się kończy.

2. URL następnej strony:

      {
    "data": [... ],
    "next_page": "https://api.twojsklep.pl/carts?page=2&limit=50"
  }

Gdy odpowiedź zawiera pole next_page z pełnym URL-em, Koszyk.pro pobierze tę stronę bezpośrednio. Przydatne gdy Twoje API generuje podpisane URL-e stron.

Ważne: Paginacja zatrzymuje się po maksymalnie 10 stronach na jeden cykl synchronizacji. Jeśli masz więcej niż 500–1000 koszyków, używaj parametru since, aby ograniczyć liczbę zwracanych wyników.

Widget JS

Widget JavaScript zbiera zdarzenia po stronie przeglądarki klienta i przesyła je do Koszyk.pro w czasie rzeczywistym. Jest to najszybszy sposób integracji — działa bez konfiguracji API.

Instalacja

Wklej poniższy snippet przed zamykającym tagiem </body> na każdej stronie swojego sklepu:

<script>
window.koszyk = window.koszyk || { q: [] };
window.koszyk.q = window.koszyk.q || [];
window.koszyk.q.push(['init', 'TWOJ_TOKEN', { platform: 'custom' }]);
</script>
<script async src="https://app.koszyk.pro/widget/koszyk-widget.min.js"></script>

Wartość TWOJ_TOKEN znajdziesz w panelu Koszyk.pro, w ustawieniach sklepu.

Automatyczna detekcja

Widget automatycznie wykrywa typowe elementy i strony sklepu:

  • Przycisk „Dodaj do koszyka" — elementy z atrybutem [data-add-to-cart] lub klasą .add-to-cart.
  • Strony koszyka/checkout — adresy URL zawierające /checkout lub /koszyk.
  • Strony potwierdzenia — adresy URL zawierające /dziekujemy lub /potwierdzenie (automatycznie oznaczają koszyk jako odzyskany).
  • Pola email — elementy input[type="email"] na stronach checkout — widget automatycznie przechwytuje wpisany email i identyfikuje klienta.

Ręczne wysyłanie danych (JavaScript API)

Jeśli automatyczna detekcja nie wystarczy, możesz ręcznie wysyłać dane do Koszyk.pro za pomocą JavaScript API:

Identyfikacja klienta:

koszyk('identify', {
email: 'klient@example.com',
firstName: 'Jan',
lastName: 'Kowalski'
});

Aktualizacja koszyka:

koszyk('cart:update', {
id: 'cart-123',
items: [
{ id: 'prod-1', name: 'Produkt A', price: '49.99', quantity: 2 },
{ id: 'prod-2', name: 'Produkt B', price: '29.99', quantity: 1 }
],
total: '129.97',
currency: 'PLN'
});

Wyczyszczenie koszyka (np. po złożeniu zamówienia):

koszyk('cart:clear');

Zdarzenie zakończenia zamówienia:

koszyk('event', 'order_completed', {
order_id: 'order-456'
});

Przekazywanie koszyka z checkoutu

Na stronie checkoutu (tam gdzie klient wpisuje adres email) możesz wywołać koszyk('checkout', ...) z pełnymi danymi koszyka. Endpoint /api/v1/track/:token/checkout jest idempotentny per (store_id, email) — wielokrotne wywołania z tym samym adresem aktualizują ten sam koszyk bez duplikatów.

Kiedy wywoływać: po blur pola email (gdy klient z niego wyjdzie) oraz po submit formularza zamówienia. Dzięki blur łapiesz adres nawet wtedy, gdy klient porzuci stronę bez submitowania.

Ważne: dane koszyka (suma, lista produktów, linki, obrazki) muszą być wyrenderowane po stronie backendu Twojego sklepu. Snippet pokazuje tylko strukturę payloadu — podmień wartości przykładowe realnymi danymi.

Pełny przykład z listenerami:

<script>
(function () {
  var form = document.querySelector('form#checkout-form');
  var emailInput = form && form.querySelector('input[type="email"]');
  if (!form || !emailInput) return;

  function pushCart() {
    var value = (emailInput.value || '').trim();
    if (!value) return;

    koszyk('checkout', {
      email: value,
      cart: {
        total: 249.90,
        currency: 'PLN',
        items: [
          {
            product_id: 'SKU-12345',
            name: 'Nazwa produktu',
            price: 199.90,
            quantity: 1,
            image_url: 'https://sklep.pl/images/nike-air.jpg',
            product_url: 'https://sklep.pl/buty-nike-air'
          }
        ]
      }
    });
  }

  emailInput.addEventListener('blur', pushCart);
  form.addEventListener('submit', pushCart);
})();
</script>

Nazwy pól: domyślnie używaj snake_case (image_url, product_url). Backend akceptuje również camelCase (imageUrl, productUrl) oraz legacy url — dla kompatybilności wstecznej. Pełna specyfikacja payloadu: docs/widget-api.md.

Konfiguracja widgetu

Po dodaniu sklepu przejdź do Sklepy → [Twój sklep] → Konfiguracja widgetu, aby dostosować zachowanie widgetu do swojej platformy. Konfiguracja jest podzielona na cztery sekcje.

Detekcja stron (URL patterns)

Widget rozpoznaje strony checkout i podziękowania na podstawie fragmentów URL. Domyślne wartości działają z większością platform, ale możesz je zmienić:

Ustawienie Domyślne wartości Opis
Ścieżki checkout /checkout, /zamowienie, /koszyk Gdy URL zawiera dowolny z tych fragmentów, widget wysyła event checkout_started i przechwytuje email z formularza.
Ścieżki „dziękujemy" /thank, /dziekujemy, /success, /potwierdzenie Gdy URL zawiera dowolny z tych fragmentów, widget wysyła event order_completed i automatycznie oznacza koszyk jako odzyskany.

W polu konfiguracyjnym wpisz fragmenty URL — po jednym na linię. Widget sprawdza, czy bieżący URL zawiera dany fragment (nie musi być dokładnym dopasowaniem).

Selektory CSS

Widget automatycznie nasłuchuje na elementy DOM pasujące do skonfigurowanych selektorów CSS. Domyślne wartości:

Element Domyślny selektor Opis
Przycisk „dodaj do koszyka" [data-add-to-cart], .add-to-cart Kliknięcie tego elementu triggeruje aktualizację koszyka
Pole email input[type="email"], input[name="email"] Widget automatycznie przechwytuje wpisany email
Formularz checkout form[action*="checkout"], .checkout-form Formularz, z którego przechwytywany jest email

Jeśli Twoja platforma używa innych selektorów (np. .btn-add-cart lub #order-email), zmień je w konfiguracji widgetu. Selektory CSS obsługują pełną składnię — możesz używać klas, atrybutów, ID i selektorów złożonych (oddzielonych przecinkami).

Wygląd popupu

Popup do zbierania emaili można w pełni dostosować:

  • Nagłówek — główny tekst popupu (domyślnie: „Zapisz swój koszyk!")
  • Podtytuł — dodatkowy opis zachęcający do podania emaila
  • Tekst przycisku — etykieta przycisku CTA (domyślnie: „Zapisz")
  • Kolor główny — kolor przycisku i akcentów (domyślnie: #3B82F6)
  • Kolor tła — kolor tła okna popupu (domyślnie: #FFFFFF)

Podgląd na żywo w panelu Koszyk.pro pozwala zobaczyć efekt zmian jeszcze przed zapisaniem konfiguracji.

Wyzwalacze popupu

Popup wyświetla się maksymalnie raz na sesję. Dostępne wyzwalacze:

  • Exit intent — popup pojawia się, gdy kursor myszy opuści obszar strony (działa tylko na komputerach).
  • Dodanie do koszyka — popup wyświetla się po dodaniu produktu do koszyka, jeśli klient nie jest jeszcze zidentyfikowany.

Dodatkowo dostępne jest ustawienie przechwytywanie emaila z checkout — automatycznie zapisuje email wpisany w formularzu zamówienia, nawet bez interakcji z popupem.

Tracking API (REST)

Oprócz widgetu JavaScript, Koszyk.pro udostępnia REST API do śledzenia koszyków i klientów. API jest przydatne do integracji server-to-server lub gdy potrzebujesz pełnej kontroli nad przesyłanymi danymi.

Wszystkie endpointy używają tokenu widgetu (STORE_TOKEN) do identyfikacji sklepu. Token znajdziesz w panelu Koszyk.pro → Sklepy → [Twój sklep] → Konfiguracja widgetu.

Identyfikacja klienta

POST /api/v1/track/STORE_TOKEN/identify
Content-Type: application/json

{
  "sessionId": "kp_abc123",
  "email": "klient@example.com",
  "firstName": "Jan",
  "lastName": "Kowalski",
  "phone": "+48123456789",
  "source": "checkout"
}

Parametry:

  • email — adres email klienta (wymagany)
  • sessionId — identyfikator sesji z widgetu (opcjonalny)
  • firstName, lastName — imię i nazwisko (opcjonalne)
  • phone — numer telefonu (opcjonalny)
  • source — źródło identyfikacji, np. "popup", "checkout" (opcjonalne)

Odpowiedź: {"status": "ok", "contactId": "uuid"}

Aktualizacja koszyka

POST /api/v1/track/STORE_TOKEN/cart
Content-Type: application/json

{
  "sessionId": "kp_abc123",
  "cart": {
    "id": "cart-123",
    "items": [
      {
        "id": "prod-1",
        "name": "Koszulka bawełniana",
        "price": "49.99",
        "quantity": 2,
        "imageUrl": "https://sklep.pl/img/koszulka.jpg",
        "productUrl": "https://sklep.pl/koszulka"
      }
    ],
    "total": "99.98",
    "currency": "PLN"
  }
}

Parametry:

  • sessionId — identyfikator sesji (wymagany)
  • cart.id — identyfikator koszyka w Twoim systemie (opcjonalny)
  • cart.items — lista produktów (maks. 100). Każdy produkt: id, name, price, quantity, imageUrl, productUrl
  • cart.total — łączna wartość koszyka
  • cart.currency — waluta ISO 4217 (domyślnie "PLN")

Odpowiedź: {"status": "ok", "cartId": "uuid"}

Śledzenie zdarzeń

POST /api/v1/track/STORE_TOKEN/event
Content-Type: application/json

{
  "sessionId": "kp_abc123",
  "event": "order_completed",
  "properties": {
    "orderId": "ORD-456"
  }
}

Obsługiwane zdarzenia:

  • checkout_started — klient rozpoczął proces zamówienia
  • order_completed — zamówienie złożone (automatycznie oznacza koszyk jako odzyskany)
  • page_viewed, cart_viewed — inne zdarzenia (zapisywane do logów)

Raportowanie konwersji (server-to-server)

Jeśli nie możesz użyć widgetu JS do raportowania zamówień (np. headless e-commerce, integracja backend-to-backend), użyj endpointu /conversion:

POST /api/v1/track/STORE_TOKEN/conversion
Content-Type: application/json

{
  "email": "klient@example.com",
  "orderId": "ORD-123"
}

Parametry:

  • email — adres email klienta (wymagany)
  • orderId — identyfikator zamówienia (opcjonalny, zapisywany w metadanych)

Ten endpoint nie wymaga sessionId — identyfikuje koszyk po emailu. System znajdzie najnowszy porzucony koszyk dla danego emaila, oznaczy go jako odzyskany i automatycznie zatrzyma sekwencję emaili. Jeśli koszyk nie istnieje, endpoint zwróci {"status": "ok", "recovered": false} — nie jest to błąd.

Przykład z curl:

curl -X POST https://app.koszyk.pro/api/v1/track/YOUR_TOKEN/conversion \
-H "Content-Type: application/json" \
-d '{"email": "klient@example.com", "orderId": "ORD-123"}'

Szablony i sekwencje emaili

Po skonfigurowaniu zbierania koszyków, ustaw automatyczne przypomnienia emailowe.

Szablony emaili

W sekcji Szablony w panelu Koszyk.pro znajdziesz gotowe szablony systemowe oraz możliwość tworzenia własnych. Każdy szablon obsługuje dynamiczne zmienne:

  • {{customer_name}} — imię i nazwisko klienta
  • {{store_name}} — nazwa Twojego sklepu
  • {{cart_total}} — łączna wartość koszyka
  • {{{recovery_url}}} — link do odzyskania koszyka (potrójne klamry — nie escapuje HTML)
  • {{#products}}...{{/products}} — sekcja z listą produktów (wewnątrz: {{products.name}}, {{products.price}}, {{products.quantity}})

Szablony systemowe można zduplikować jako własne i dowolnie modyfikować. Edytor oferuje podgląd na żywo z danymi przykładowymi.

Sekwencje emaili (Flows)

W sekcji Flows stworzysz automatyczne sekwencje przypomnień. Każda sekwencja składa się z kroków:

  1. Krok 1 — np. 30 minut po porzuceniu: „Zapomniałeś o koszyku?"
  2. Krok 2 — np. 24 godziny później: „Twoje produkty nadal czekają"
  3. Krok 3 — np. 3 dni później: „Ostatnia szansa — 10% rabatu!"

Każdy krok ma konfigurowalny czas opóźnienia (w minutach) i przypisany szablon. Sekwencja zatrzymuje się automatycznie, gdy klient złoży zamówienie (dzięki eventowi order_completed lub endpointowi /conversion).

Linki odzyskiwania

Każdy email zawiera unikalny link odzyskiwania w formacie https://app.koszyk.pro/r/TOKEN. Po kliknięciu:

  1. Koszyk.pro rejestruje kliknięcie w statystykach
  2. Klient jest przekierowany do Twojego sklepu

Dla platform Custom link prowadzi do głównego adresu URL sklepu. Użyj zmiennej {{{recovery_url}}} w szablonach, aby wstawić link.

Webhooki push

Jako alternatywę dla pollingu API możesz wysyłać dane o koszykach bezpośrednio do Koszyk.pro za pomocą webhooków push. Dzięki temu dane trafiają do systemu natychmiast — bez czekania na cykl synchronizacji.

Endpoint webhookowy znajdziesz w panelu sklepu, w sekcji „Webhooki". Format danych jest identyczny jak w przypadku API koszyków (te same pola, te same warianty nazw — patrz Konfiguracja API).

Wyślij żądanie POST na endpoint webhookowy z danymi koszyka w treści (body) w formacie JSON. Koszyk.pro automatycznie rozpozna format i znormalizuje dane.

FAQ

Jak rozpoznawany jest koszyk?

Koszyk identyfikowany jest po polu id, platform_cart_id lub cart_id. Jeśli koszyk z danym identyfikatorem już istnieje w systemie, zostanie zaktualizowany — nie utworzy się duplikat.

Czy potrzebuję API jeśli mam widget?

Nie. Widget JavaScript jest w pełni samodzielnym źródłem danych. Jeśli zainstalujesz widget na swoich stronach, koszyki będą zbierane automatycznie w czasie rzeczywistym. API jest opcjonalne — przydaje się jako dodatkowe zabezpieczenie (np. dla klientów z zablokowanym JavaScript).

Moje API zwraca dane w innym formacie

Koszyk.pro akceptuje elastyczne nazwy pól — np. id zamiast platform_cart_id, price zamiast unit_price. Sprawdź tabelę akceptowanych nazw w sekcji Konfiguracja API. Jeśli Twoje API używa zupełnie innego formatu, skontaktuj się z nami — pomożemy z integracją.

Widget nie wykrywa dodania do koszyka

Widget automatycznie nasłuchuje na elementy z atrybutem [data-add-to-cart] lub klasą .add-to-cart. Jeśli Twój przycisk „Dodaj do koszyka" nie ma żadnego z tych selektorów, masz trzy opcje:

  • Zmień selektor CSS — w Konfiguracji widgetu wpisz selektor pasujący do Twojego przycisku (np. .btn-buy lub #add-button).
  • Dodaj atrybut — umieść data-add-to-cart na przycisku dodającym produkt do koszyka.
  • Użyj JavaScript API — po dodaniu produktu wywołaj ręcznie koszyk('cart:update', ...) z aktualnym stanem koszyka.

Widget nie wykrywa strony „dziękujemy"

Domyślnie widget rozpoznaje strony z fragmentami /thank, /dziekujemy, /success, /potwierdzenie w URL. Jeśli Twoja strona potwierdzenia zamówienia ma inny URL:

  • Dodaj odpowiedni fragment w Konfiguracji widgetu → Ścieżki „dziękujemy".
  • Alternatywnie, wywołaj koszyk('event', 'order_completed', ...) z JavaScript po złożeniu zamówienia.
  • Dla integracji backend-to-backend, użyj endpointu /conversion.

Jakie są limity API?

Tracking API (/api/v1/track/) pozwala na 100 zapytań na minutę per adres IP. Endpoint Capture (/api/capture/) — 60 na minutę. Limity dotyczą IP, nie tokenu sklepu.

Jak działa link odzyskiwania w emailu?

Link ma format https://app.koszyk.pro/r/TOKEN. Po kliknięciu klient jest przekierowany (302) do adresu URL Twojego sklepu. Kliknięcie jest rejestrowane w statystykach. Dla platform Custom link prowadzi do głównego URL sklepu — jeśli chcesz przekierować do konkretnej strony koszyka, wstaw odpowiedni URL bezpośrednio w szablonie.