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:
- Zaloguj się do swojego konta w Koszyk.pro.
- Przejdź do sekcji „Sklepy" i kliknij przycisk „Dodaj sklep".
- Wybierz platformę Custom z listy dostępnych integracji.
-
Podaj nazwę i adres URL swojego sklepu
— nazwa jest dowolna (np. „Mój sklep"), a URL musi zaczynać się od
https://. - 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
/checkoutlub/koszyk. -
Strony potwierdzenia
— adresy URL zawierające
/dziekujemylub/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:
- Krok 1 — np. 30 minut po porzuceniu: „Zapomniałeś o koszyku?"
- Krok 2 — np. 24 godziny później: „Twoje produkty nadal czekają"
- 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:
- Koszyk.pro rejestruje kliknięcie w statystykach
- 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-buylub#add-button). -
Dodaj atrybut
— umieść
data-add-to-cartna 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.