> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aftersell.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Przegląd

> Jak działa Aftersell Cart SDK: globalny punkt wejścia, cztery części API, kiedy się ładuje i jak bezpiecznie uruchamiać na nim kod.

**Cart SDK** to interfejs JavaScript API dla koszyka Aftersell Cart w Twoim sklepie. Pozwala zmieniać zachowanie koszyka, reagować na działania kupujących oraz odczytywać lub zmieniać zawartość koszyka z poziomu kodu.

Kod SDK uruchamiasz przez [Skrypty niestandardowe](/pl/aftersell/cart/custom-scripts) lub przez tryb React [bloku Custom code](/pl/aftersell/cart/custom-code-blocks), jeśli blok ma renderować własny interfejs.

<Note>
  Wiele z tego, o co sprzedawcy proszą SDK, jest już dostępne jako ustawienie. Zanim napiszesz skrypt, sprawdź, czy [blok koszyka](/pl/aftersell/cart/blocks-overview), [warunki według rynku/kraju/waluty](/pl/aftersell/cart/blocks-overview#show-or-hide-by-market-country-or-currency) lub [ustawienie koszyka](/pl/aftersell/cart/cart-settings) już to robi. One działają dalej po przeprojektowaniu koszyka, a Twój skrypt może przestać.
</Note>

<div id="the-global-entry-point">
  ## Globalny punkt wejścia
</div>

Wszystko opiera się na jednym obiekcie globalnym:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart
```

<Note>
  **Każdy fragment kodu w tej dokumentacji zapisuje `window.aftersell.cart` w pełnej formie**, więc każdy z nich działa samodzielnie po wklejeniu. Jednorazowe utworzenie aliasu (`const cart = window.aftersell.cart;`) i używanie dalej `cart` jest w pełni poprawne i bezpieczne nawet przed załadowaniem koszyka. Pamiętaj tylko, aby dołączyć tę linię, jeśli skracasz fragment, ponieważ samo `cart` bez niej rzuca błąd `cart is not defined`.
</Note>

Pracę wykonują cztery części:

<Columns cols={2}>
  <Card title="Configure" icon="sliders" href="/pl/aftersell/cart/sdk-configure">
    Ustaw zachowanie koszyka: kiedy otwiera się szuflada, jak formatowane są kwoty, czy Aftersell przechwytuje dodawanie do koszyka.
  </Card>

  <Card title="Events" icon="tower-broadcast" href="/pl/aftersell/cart/sdk-events">
    Reaguj na to, co się dzieje: koszyk się załadował, dodano produkt, otwarto szufladę, kliknięto checkout.
  </Card>

  <Card title="Actions" icon="wand-magic-sparkles" href="/pl/aftersell/cart/sdk-actions">
    Odczytuj i zmieniaj koszyk: otwórz go, dodaj produkt, zaktualizuj ilość, odczytaj bieżący stan.
  </Card>

  <Card title="Hooks" icon="plug" href="/pl/aftersell/cart/sdk-hooks">
    Zmieniaj sposób działania samego koszyka: ukrywaj lub zmieniaj etykiety pozycji, zmieniaj ich kolejność, dołączaj dodatkowe dane, kontroluj dodawanie do koszyka.
  </Card>
</Columns>

<Note>
  Jeśli któryś z Twoich skryptów przestał odpalać się przy add-to-cart, zacznij od [Przechwytywania add-to-cart](/pl/aftersell/cart/add-to-cart-interception). Wyjaśnia, dlaczego Aftersell przejmuje dodawanie, i wszystkie sposoby, by wyłączyć z tego pojedynczy formularz.
</Note>

Plus trzy mniejsze elementy:

| Element      | Do czego służy                                                               |
| ------------ | ---------------------------------------------------------------------------- |
| `ready()`    | Promise, który rozwiązuje się po pierwszym załadowaniu koszyka.              |
| `context`    | Renderowany po stronie serwera kontekst kupującego, dostępny synchronicznie. |
| `shadowRoot` | Shadow root koszyka, do wyszukiwania elementów wewnątrz szuflady.            |

<div id="events-actions-or-hooks">
  ## Zdarzenia, akcje czy hooki?
</div>

Te trzy łatwo pomylić, a wybranie niewłaściwego to najczęstszy powód, dla którego skrypt nie robi tego, czego oczekiwał jego autor:

| Chcesz…                                             | Użyj          | Przykład                                           |
| --------------------------------------------------- | ------------- | -------------------------------------------------- |
| Uruchomić kod *gdy coś się wydarzy*                 | **Zdarzenie** | Wyślij zdarzenie analityczne po dodaniu produktu.  |
| *Zmienić zawartość* koszyka                         | **Akcja**     | Dodaj darmowy prezent, gdy suma przekroczy \$50.   |
| Zmienić *sposób działania lub renderowania koszyka* | **Hook**      | Ukryj pozycje z darmowymi prezentami w szufladzie. |

Najważniejsza różnica: **akcja zmienia rzeczywisty koszyk kupującego** (i jego sumę), podczas gdy **hook zmienia tylko to, co się renderuje**. Ukrycie pozycji hookiem pozostawia ją w koszyku i w sumie; usunięcie jej akcją wyjmuje ją naprawdę.

<div id="how-and-when-it-loads">
  ## Jak i kiedy się ładuje
</div>

Koszyk ładuje się w dwóch etapach, a SDK jest zbudowane tak, abyś nie musiał myśleć o kolejności:

1. Mały **stub** tworzy `window.aftersell.cart` natychmiast, więc obiekt zawsze istnieje.
2. Pełne SDK ładuje się chwilę później i przejmuje kontrolę, ulepszając stub w miejscu, więc wcześniej zapisana referencja nadal działa.

Daje to dwie kategorie wywołań:

<Columns cols={2}>
  <Card title="Wywołania konfiguracyjne: bezpieczne od razu" icon="circle-check">
    `configure(...)`, `events.on(...)` i każde wywołanie `hooks.register*`. Buforowane przed startem i odtwarzane w kolejności po załadowaniu SDK. Umieszczaj je na początku skryptu.
  </Card>

  <Card title="Akcje: poczekaj na ready()" icon="clock">
    Wszystko pod `actions.*`. Uruchamiaj je wewnątrz `ready()` lub obsługi zdarzenia. Wywołane zbyt wcześnie wypisują ostrzeżenie w konsoli i nic nie robią — bezpiecznie: te asynchroniczne i tak się rozwiązują, więc łańcuch `.then()` się nie zepsuje.
  </Card>
</Columns>

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
// Set-up: fine at the top level, before the cart has loaded.
window.aftersell.cart.configure({ open_on_add_to_cart: 'always' });

window.aftersell.cart.events.on('item_added', (payload) => {
  console.log('Added', payload.item.title);
});

// Actions: wait until the cart is ready.
window.aftersell.cart.ready().then(() => {
  const state = window.aftersell.cart.actions.getCart();
  console.log(state.itemCount, 'items');
});
```

<div id="ready">
  ### ready()
</div>

`ready()` zwraca Promise, który rozwiązuje się, gdy pierwsze ładowanie koszyka **się zakończy**. Rozwiązuje się zarówno przy niepowodzeniu, jak i sukcesie, więc kupujący z niestabilnym połączeniem nigdy nie zostawi Twojego skryptu w zawieszeniu. Sprawdzaj, czy `getCart()` zwraca `null`, zamiast zakładać, że koszyk dotarł.

Wywołanie `ready()` po tym, jak koszyk już się załadował, rozwiązuje się natychmiast, więc można go bezpiecznie używać jako ogólnej bramki „koszyk już istnieje” w dowolnym miejscu kodu.

<Tip>
  Nie potrzebujesz `ready()` wewnątrz obsługi zdarzenia. Zanim wystrzeli `cart_loaded`, `cart_updated` lub `item_added`, koszyk jest już załadowany i akcje można bezpiecznie wywoływać.
</Tip>

<div id="context">
  ## context
</div>

`window.aftersell.cart.context` przechowuje dane kupującego renderowane przez serwer, dostępne synchronicznie, bez potrzeby `ready()`. Używaj go do rozgałęzień według rynku lub kraju, które muszą nastąpić przed załadowaniem koszyka.

| Pole                      | Opis                                                                                    | Dostępne przed startem                  |
| ------------------------- | --------------------------------------------------------------------------------------- | --------------------------------------- |
| `shopify_market`          | Rynek Shopify kupującego.                                                               | Tak                                     |
| `customer_country`        | Dwuliterowy kod kraju.                                                                  | Tak                                     |
| `customer_currency`       | Kod aktywnej waluty.                                                                    | Tak                                     |
| `money_format`            | Format kwot Shopify sklepu.                                                             | Tak                                     |
| `backend_url`             | Bezpośredni host backendu, używany jako rezerwa, gdy app proxy nie jest skonfigurowane. | Tak                                     |
| `storefront_access_token` | Token do wywołań Storefront API.                                                        | **Nie** — dodawany, gdy koszyk startuje |

<Warning>
  `storefront_access_token` to jedyne pole `context`, którego serwer nie renderuje do `cart.context`. Jest dodawane do `context`, gdy koszyk startuje, więc odczytanie go na początku skryptu zwraca `undefined`. Najpierw poczekaj na `window.aftersell.cart.ready()`.
</Warning>

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
if (window.aftersell.cart.context.customer_country === 'CA') {
  // Canada-only behavior, decided before the cart loads.
}
```

<Note>
  Aby pokazywać różne ustawienia bloków według rynku, kraju lub waluty, użyj zamiast tego [warunków w edytorze koszyka](/pl/aftersell/cart/blocks-overview#show-or-hide-by-market-country-or-currency). Skrypt nie jest potrzebny. Pełny interfejs warunków jest dziś dostępny w [Rewards](/pl/aftersell/cart/rewards-block#per-market-rewards).
</Note>

<div id="shadowroot">
  ## shadowRoot
</div>

Koszyk renderuje się wewnątrz shadow root, więc `document.querySelector` **nie widzi niczego wewnątrz szuflady**. Aby dosięgnąć elementu w koszyku, odpytaj shadow root:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
const root = window.aftersell.cart.shadowRoot;
const button = root?.querySelector('.cart-external-checkout-button');
```

Celuj w te same **publiczne klasy `cart-external-*`**, których używa [Custom CSS](/pl/aftersell/cart/custom-css). To są wspierane uchwyty. Bliźniacze klasy `cart-internal-*` to wewnętrzna maszyneria koszyka, więc odpytuj zamiast nich te zewnętrzne.

<Warning>
  Sięgaj po shadow root tylko wtedy, gdy żaden blok, ustawienie ani hook nie wykonuje zadania. Hook przetrwa przeprojektowanie koszyka; zapytanie DOM to problem utrzymaniowy Twojego kodu.
</Warning>

Shadow root istnieje dopiero po starcie koszyka, więc odczytuj go wewnątrz `ready()` lub obsługi zdarzenia, a nie na początku skryptu.

<div id="debugging">
  ## Debugowanie
</div>

Zepsuty skrypt nigdy nie może wyłączyć dodawania do koszyka ani szuflady, dlatego SDK izoluje błędy, zamiast pozwalać im się rozprzestrzeniać. Miejsce, w którym błąd się ujawnia, zależy od tego, co się zepsuło:

| Co zawiodło                                                                    | Gdzie się to pokazuje                                                    |
| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------ |
| Twój skrypt rzucił błąd na najwyższym poziomie                                 | `console.error`, ze wskazaniem linii i tego, co nigdy się nie uruchomiło |
| Obsługa [zdarzenia](/pl/aftersell/cart/sdk-events) rzuciła błąd                | `console.error`; pozostałe obsługi nadal działają                        |
| [Hook](/pl/aftersell/cart/sdk-hooks) rzucił błąd                               | Cisza. Trafia do kanału debugowania poniżej                              |
| [Akcja](/pl/aftersell/cart/sdk-actions) uruchomiona przed załadowaniem koszyka | `console.warn`; wywołanie nic nie robi                                   |

<div id="when-your-script-throws">
  ### Gdy Twój skrypt rzuca błąd
</div>

Skrypt niestandardowy **zatrzymuje się na pierwszym błędzie**, więc każde `configure`, `events.on` i `hooks.register*` poniżej tej linii nigdy się nie uruchamia. Koszyk mówi o tym wprost:

```
[aftersell-cart] Initialization script error on line 12 — 4 more line(s) did not run;
any configure/events/hooks below are unregistered.
```

To komunikat, którego należy szukać, gdy obsługa, którą na pewno zarejestrowano, nigdy nie odpala: prawdopodobnie nigdy nie została osiągnięta. Numer linii to instrukcja najwyższego poziomu, na której zatrzymało się wykonanie, a nie wewnętrzna funkcja, która rzuciła błąd; jest pomijany zamiast zgadywany, jeśli stos przeglądarki nie nadaje się do użytku.

Twoje skrypty działają też pod własnymi nazwami plików, więc w DevTools pojawiają się jako `aftersell-cart-init.js` i `aftersell-cart-cart-update.js`. Możesz otworzyć je w panelu Sources i ustawiać punkty przerwania jak w każdym innym pliku.

<div id="the-debug-channel">
  ### Kanał debugowania
</div>

Błędy hooków są celowo trzymane z dala od konsoli, aby kupujący nigdy ich nie widzieli. Trafiają zamiast tego tutaj:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
// After reproducing the problem, inspect what was swallowed:
window.aftersellCartDebugEvents.filter((entry) => entry.level === 'ERROR');

// Or watch them live:
window.addEventListener('aftersell-cart-debug', (event) => console.log(event.detail));
```

<div id="where-to-go-next">
  ## Co dalej
</div>

<Columns cols={2}>
  <Card title="Configure" icon="sliders" href="/pl/aftersell/cart/sdk-configure">
    Każda opcja, z przykładem dla każdej.
  </Card>

  <Card title="Events" icon="tower-broadcast" href="/pl/aftersell/cart/sdk-events">
    Każde zdarzenie, kiedy się odpala i czego nie robić w obsłudze.
  </Card>

  <Card title="Actions" icon="wand-magic-sparkles" href="/pl/aftersell/cart/sdk-actions">
    Każda akcja, z fragmentem kodu dla każdej.
  </Card>

  <Card title="Hooks" icon="plug" href="/pl/aftersell/cart/sdk-hooks">
    Każdy hook i jak rejestracje się składają.
  </Card>

  <Card title="Obiekt koszyka" icon="table-list" href="/pl/aftersell/cart/sdk-cart-object">
    Struktura koszyka i jego pozycji.
  </Card>

  <Card title="Przypadki użycia" icon="book-open" href="/pl/aftersell/cart/sdk-use-cases">
    Kompletne, gotowe do uruchomienia rozwiązania częstych próśb.
  </Card>
</Columns>
