Jak osadzić 3D Viewer, Konfigurator i Personalizator za pomocą iframe + postMessage (Szybki 5-minutowy setup)
Wstęp
Chcesz dodać do swojego sklepu podgląd 3D/AR i personalizację produktu w czasie rzeczywistym bez miesięcy programowania? Możesz to zrobić przez bezpieczne osadzenie w iframe, handshake postMessage i krótkotrwały token sesji tworzony przez Twój backend za pomocą Alter Product Public API. W ten sposób możesz osadzić 3D Viewer, Configurator lub Customizer i stworzyć interaktywne doświadczenie zakupowe, które podnosi konwersję, skraca checkout i zmniejsza liczbę zwrotów.
Ten przewodnik pokazuje aktualną integrację dla własnego stacku. Zobaczysz, jak dodać iframe, skonfigurować parametry URL, zainicjalizować sesję embedu, podłączyć zdarzenia koszyka przez postMessage i bezpiecznie trzymać dane API po stronie serwera. Rozwiązanie pasuje do nowoczesnych CMS-ów, storefront builderów oraz własnych lub headlessowych stacków e-commerce.
Szybki start: checklista bezpiecznego osadzenia
- Utwórz projekt w Alter Product.
- Wygeneruj dane API w E-commerce Settings → API Credentials. Przechowuj je wyłącznie po stronie serwera.
- Dodaj domenę sklepu w E-commerce Settings → Integration.
- Umieść adres Viewer, Configurator lub Customizer w
iframe. - Obsłuż handshake
postMessage: iframe wysyłaALTER_CHILD_HELLO, a Twoja strona odpowiadaALTER_PARENT_ACK. - Utwórz krótkotrwałą sesję embedu z backendu przez
POST /public-api/v1/embed/session, a potem przekaż token z powrotem do iframe. - Nasłuchuj zdarzeń koszyka i danych, takich jak
ALTER_VIEWER_ADD_TO_CART,ALTER_CONFIGURATOR_ADD_TO_CARTiALTER_CUSTOMIZER_ADD_TO_CART.
Tip: Real-time pricing jest dostępny w każdym planie. White-label branding, osadzanie na własnej stronie, brandowane Customizery i server-side embedded storage są dostępne od planu Business.

Krok 1: Osadzenie przez iframe
Każdy moduł ma własny adres URL. Dodaj go do strony za pomocą iframe, a następnie autoryzuj runtime przez handshake i token sesji pokazane w kroku 3. Iframe jest kontenerem wizualnym; dostęp zostaje przyznany dopiero po utworzeniu prawidłowej sesji embedu przez Twój backend.
Viewer (podgląd 3D/AR)
<iframe src="https://alterproduct.com/app/viewer/40?add_to_cart=1&nav=1" width="100%" height="640" title="Alter Product Viewer"></iframe>Configurator (warianty + cena na żywo)
<iframe src="https://alterproduct.com/app/configurator/41?add_to_cart=1" width="100%" height="720" title="Alter Product Configurator"></iframe>Customizer (pełna personalizacja + print-ready)
<iframe src="https://alterproduct.com/app/customizer/44" width="100%" height="800" title="Alter Product Customizer"></iframe>Uwaga: nav=1 może wyświetlać brandowany górny pasek, jeśli branding jest dostępny w Twoim planie. Na mobile AR działa w Viewerze lub Configuratorze - bez dodatkowych aplikacji.
Krok 2: Stylowanie i parametry URL
Możesz dopasować doświadczenie zakupowe, dodając parametry URL do iframe. Najczęściej używane:
nav=0|1- pokazuje lub ukrywa górny pasek nawigacyjny.add_to_cart=0|1- pokazuje lub ukrywa przycisk „Add to Cart”.bcg=value- ustawia tryb lub wartość tła.env=1- wybiera oświetlenie środowiskowe.light_intensity=0–2- kontroluje intensywność światła.
Pełne tabele obsługiwanych parametrów znajdziesz w dokumentacji:
Na koniec dopasuj kontener iframe za pomocą CSS (aspect ratio, zaokrąglenia, odstępy), aby modele 3D wyglądały wygodnie i immersyjnie. Upewnij się też, że całość pasuje do stylu Twojej strony - spójna oprawa wzmacnia markę i daje klientom płynniejsze doświadczenie.
Krok 3: Integracja przez postMessage (Viewer, Configurator, Customizer)
postMessage pozwala Twojej stronie komunikować się z osadzonym modułem i odbierać zdarzenia z modułu. Aktualny runtime zaczyna od handshake’u z nonce, a następnie prosi Twoją stronę o token sesji. Frontend nigdy nie powinien wywoływać Alter Product Public API z prywatnymi danymi API - utwórz mały endpoint backendowy, który wykona połączenie server-to-server.
Uwaga: Zawsze weryfikuj event.origin, aby akceptować wiadomości tylko z zaufanego źródła.
Viewer - handshake, token sesji i zdarzenia koszyka
<iframe
id="viewerWidget"
src="https://alterproduct.com/app/viewer/1?add_to_cart=1&nav=1"
title="Alter Product Viewer"
width="100%"
height="560"
style="border:0;border-radius:12px;"
loading="lazy"></iframe>
<script>
const ALLOWED_ORIGIN = "https://alterproduct.com";
const viewer = document.getElementById("viewerWidget");
async function createEmbedSession(payload) {
const response = await fetch("/api/alter/embed-session", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
tool: "viewer",
origin: window.location.origin,
runtimePayload: payload
})
});
if (!response.ok) throw new Error("Could not create embed session");
return response.json(); // expected: { token }
}
function requestViewerData() {
viewer.contentWindow.postMessage(
{ type: "ALTER_VIEWER_GET_PRODUCT_DATA" },
ALLOWED_ORIGIN
);
}
window.addEventListener("message", async (event) => {
if (event.origin !== ALLOWED_ORIGIN) return;
const { type, payload } = event.data || {};
if (type === "ALTER_CHILD_HELLO") {
viewer.contentWindow.postMessage(
{ type: "ALTER_PARENT_ACK", payload: { nonce: payload?.nonce } },
ALLOWED_ORIGIN
);
return;
}
if (type === "ALTER_TOOL_INIT_SESSION") {
try {
const session = await createEmbedSession(payload);
viewer.contentWindow.postMessage(
{ type: "ALTER_TOOL_SESSION_READY", payload: { token: session.token } },
ALLOWED_ORIGIN
);
} catch (error) {
viewer.contentWindow.postMessage(
{ type: "ALTER_TOOL_SESSION_ERROR", payload: { message: error.message } },
ALLOWED_ORIGIN
);
}
return;
}
if (type === "ALTER_VIEWER_ADD_TO_CART") {
console.log("[Viewer] ADD_TO_CART", payload);
// TODO: add product data to your cart
}
if (type === "ALTER_VIEWER_DATA_RESPONSE") {
console.log("[Viewer] DATA_RESPONSE", payload);
// TODO: update price / variant UI
}
});
</script>Configurator - handshake, token sesji i dane produktu
<button id="getDataBtn">Pobierz skonfigurowany produkt</button>
<iframe
id="configuratorWidget"
src="https://alterproduct.com/app/configurator/1?nav=0&add_to_cart=1"
title="Alter Product Configurator"
width="100%"
height="600"
style="border:0;border-radius:12px;"
loading="lazy"></iframe>
<script>
const ALLOWED_ORIGIN = "https://alterproduct.com";
const iframe = document.getElementById("configuratorWidget");
async function createEmbedSession(payload) {
const response = await fetch("/api/alter/embed-session", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
tool: "configurator",
origin: window.location.origin,
runtimePayload: payload
})
});
if (!response.ok) throw new Error("Could not create embed session");
return response.json(); // expected: { token }
}
document.getElementById("getDataBtn").addEventListener("click", () => {
iframe.contentWindow.postMessage(
{ type: "ALTER_CONFIGURATOR_GET_PRODUCT_DATA" },
ALLOWED_ORIGIN
);
});
window.addEventListener("message", async (event) => {
if (event.origin !== ALLOWED_ORIGIN) return;
const { type, payload } = event.data || {};
if (type === "ALTER_CHILD_HELLO") {
iframe.contentWindow.postMessage(
{ type: "ALTER_PARENT_ACK", payload: { nonce: payload?.nonce } },
ALLOWED_ORIGIN
);
return;
}
if (type === "ALTER_TOOL_INIT_SESSION") {
try {
const session = await createEmbedSession(payload);
iframe.contentWindow.postMessage(
{ type: "ALTER_TOOL_SESSION_READY", payload: { token: session.token } },
ALLOWED_ORIGIN
);
} catch (error) {
iframe.contentWindow.postMessage(
{ type: "ALTER_TOOL_SESSION_ERROR", payload: { message: error.message } },
ALLOWED_ORIGIN
);
}
return;
}
if (type === "ALTER_CONFIGURATOR_ADD_TO_CART") {
console.log("[Configurator] ADD_TO_CART", payload);
// TODO: add item to your cart
}
if (type === "ALTER_CONFIGURATOR_DATA_RESPONSE") {
console.log("[Configurator] DATA_RESPONSE", payload);
// TODO: show summary / sync price & variant
}
});
</script>Customizer - token sesji, cart key i order-first flow
W Customizerze kliknięcie Add to cart zapisuje projekt klienta i tworzy zamówienie w edytowalnym flow koszyka. Domyślny edytowalny status to shopping_cart. Klient może dalej edytować projekt, gdy zamówienie ma status shopping_cart lub editable. Po zmianie statusu na realizacyjny, np. paid, processing, completed lub cancelled, edycja przez klienta zostaje zablokowana.
<iframe
id="customizerWidget"
src="https://alterproduct.com/app/customizer/1?add_to_cart=1"
title="Alter Product Customizer"
width="100%"
height="720"
style="border:0;border-radius:12px;"
loading="lazy"></iframe>
<script>
const ALLOWED_ORIGIN = "https://alterproduct.com";
const customizer = document.getElementById("customizerWidget");
async function createCustomizerSession(payload) {
const response = await fetch("/api/alter/customizer-session", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
origin: window.location.origin,
runtimePayload: payload
})
});
if (!response.ok) throw new Error("Could not create Customizer session");
return response.json(); // expected: { token, cartKey, mode }
}
window.addEventListener("message", async (event) => {
if (event.origin !== ALLOWED_ORIGIN) return;
const { type, payload } = event.data || {};
if (type === "ALTER_CHILD_HELLO") {
customizer.contentWindow.postMessage(
{ type: "ALTER_PARENT_ACK", payload: { nonce: payload?.nonce } },
ALLOWED_ORIGIN
);
return;
}
if (type === "ALTER_CUSTOMIZER_INIT_SESSION") {
try {
const session = await createCustomizerSession(payload);
customizer.contentWindow.postMessage(
{
type: "ALTER_CUSTOMIZER_SESSION_READY",
payload: {
token: session.token,
cartKey: session.cartKey,
mode: session.mode
}
},
ALLOWED_ORIGIN
);
} catch (error) {
customizer.contentWindow.postMessage(
{ type: "ALTER_CUSTOMIZER_SESSION_ERROR", payload: { message: error.message } },
ALLOWED_ORIGIN
);
}
return;
}
if (type === "ALTER_CUSTOMIZER_ADD_TO_CART") {
console.log("[Customizer] ADD_TO_CART", payload);
// TODO: store order/cart data and redirect to checkout
}
if (type === "ALTER_CUSTOMIZER_UPDATE_DESIGN") {
console.log("[Customizer] UPDATE_DESIGN", payload);
// TODO: update existing cart line/order data
}
});
</script>Dokumentacja: szczegółowe listy wiadomości i payloadów:
Tip: Zawsze dodaj swoją domenę w E-commerce Settings → Integration, weryfikuj event.origin i unikaj używania * jako target origin na produkcji.
Co otrzymujesz: aktualny payload konfiguracji lub projektu - wariant, cenę, ilość, metadane, cart key lub dane zamówienia - gotowy do synchronizacji z koszykiem albo podsumowaniem.
Krok 4: Flow Add to Cart
- Viewer:
ALTER_VIEWER_ADD_TO_CARTwysyła dane produktu, gdy użytkownik kliknie przycisk. Użyj ich, aby dodać wybrany stan produktu do koszyka. - Configurator:
ALTER_CONFIGURATOR_ADD_TO_CARTwysyła dane skonfigurowanego produktu, w tym wybrane metadane wariantu i kontekst ceny. - Customizer:
ALTER_CUSTOMIZER_ADD_TO_CARTuruchamia się po zapisaniu projektu w edytowalnym flow koszyka. To moment, aby:- zapisać ID zamówienia lub dane koszyka,
- zapisać
cartKey, jeśli Twój flow tego wymaga, - przekierować do checkoutu,
- po płatności zaktualizować status przez Public API, aby zablokować edycję przez klienta.
Krok 5: Bezpieczeństwo i compliance
- Dodaj domenę osadzenia w E-commerce Settings → Integration.
- Zawsze filtruj
event.origini nigdy nie używaj*na produkcji. - Trzymaj dane API wyłącznie na backendzie. Uwierzytelnione wywołania Public API powinny działać server-to-server.
- Twórz sesje embedu przez backend za pomocą
POST /public-api/v1/embed/session. - Używaj krótkotrwałych tokenów sesji. Tokeny embedu są przypisane do zweryfikowanego origin i wygasają automatycznie.
- Opcje white-label (logo, kolory, brandowany nav) są dostępne od planu Business.
Krok 6: Testowanie i debugowanie
- Otwórz DevTools → Console, aby monitorować logi
postMessage. - Sprawdź, czy odbierasz
ALTER_CHILD_HELLOi czy Twoja strona wysyłaALTER_PARENT_ACKz tym samym nonce. - Zweryfikuj, czy endpoint backendowy tworzy prawidłowy token sesji embedu.
- Przetestuj zmiany wariantów, zapytania o dane produktu i flow Add to Cart.
- Na mobile przetestuj AR w Viewerze lub Configuratorze.
- Jeśli nic się nie wyświetla - sprawdź dodanie domeny, tworzenie tokenu sesji i walidację
event.origin.
Opcjonalnie: Public API dla sesji embedu i zamówień Customizera
Dla głębszych workflow połącz backend z Alter Product Public API. Typowe zastosowania:
- utworzenie tokenu sesji embedu przez
POST /public-api/v1/embed/session, - pobranie zamówienia po ID,
- pobranie wielu zamówień w jednym zapytaniu,
- aktualizacja statusu po płatności,
- synchronizacja ilości,
- usuwanie porzuconych zamówień,
- pobranie produktów dostępnych dla uwierzytelnionego storefrontu.
Wszystkie uwierzytelnione zapytania Public API powinny działać server-to-server. Dzięki temu otrzymujesz płynny pipeline: projekt → koszyk → płatność → produkcja z eksportami print-ready.
Najczęstsze błędy (których warto unikać)
- Brak tokenu sesji embedu - iframe nie może zainicjalizować się bezpiecznie.
- Wywoływanie uwierzytelnionych endpointów Public API bezpośrednio z przeglądarki - dane API muszą pozostać po stronie serwera.
- Brak odpowiedzi
ALTER_PARENT_ACKlub niezgodny nonce - handshake nie przejdzie. - Brak filtra
event.origin- ryzyko bezpieczeństwa. - Domena nie została dodana w E-commerce Settings → Integration - sesja lub komunikacja może nie działać.
- Za mały iframe - ciasny widok 3D (zwiększ wysokość, dodaj border radius).
- Brak
add_to_cart=1- przycisk się nie pojawi.
FAQ
Czy mogę osadzić na dowolnym CMS-ie lub stronie?
Tak - interfejs osadzasz przez iframe. Dla produkcyjnych integracji z własnym stackiem użyj handshake’u postMessage i utwórz krótkotrwały token sesji embedu z backendu.
Czy real-time pricing jest dostępny w każdym planie?
Tak - cena aktualizuje się natychmiast we wszystkich planach.
Czy potrzebuję developera?
Do bezpiecznej integracji koszyka z własnym stackiem potrzebujesz małego endpointu backendowego, który tworzy sesje embedu i chroni dane API. Część frontendowa pozostaje lekka: iframe plus postMessage.
Czy Customizer generuje pliki print-ready?
Tak - Customizer może eksportować pliki print-ready, dostępne od planu Personal.
Czy mogę użyć własnego logo i kolorów?
Tak - white-label branding jest dostępny od planu Business.


