Viewer – Încorporare de bază pe site-ul tău

Încorporare pe ecran complet

Încorporează Viewer oriunde pe site folosind un iframe.

Important: mediul de execuție încorporat actual necesită un handshake postMessage și un token de sesiune de încorporare de scurtă durată. Backendul creează tokenul prin Alter Product Public API și îl asociază originii gazdei.

Flux:

  1. Pagina ta încarcă iframe-ul cu URL-ul Viewer.
  2. Iframe-ul trimite ALTER_CHILD_HELLO, iar pagina răspunde cu ALTER_PARENT_ACK, folosind același nonce.
  3. Iframe-ul solicită acces prin ALTER_TOOL_INIT_SESSION și payload.tool=viewer.
  4. Backendul creează un token de sesiune de încorporare, iar pagina trimite ALTER_TOOL_SESSION_READY cu token.
<!DOCTYPE html>
<html>
  <head>
    <title>Alter Product - Full Screen Embed</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style>
      * { box-sizing: border-box; }
      html, body { width: 100%; height: 100%; margin: 0; padding: 0; }
      iframe { width: 100%; height: 100%; border: 0; display: block; }
      #wrapper { width: 100%; height: 100%; }
    </style>
  </head>
  <body>
    <div id="wrapper">        
      <iframe
        id="alter-iframe"
        title="Alter Product Tool"
        src="https://alterproduct.com/app/viewer/1"
        allowfullscreen
      ></iframe>
    </div>
    <script>
      const IFRAME_ORIGIN = "https://alterproduct.com";
      const TOOL = "viewer";
      const DESIGN_ID = 1;
      const iframe = document.getElementById("alter-iframe");

      // Keep nonce per handshake (from iframe) to prevent random messages from being accepted.
      let handshakeNonce = "";
      let handshakeOk = false;

      function postToIframe(payload) {
        iframe.contentWindow.postMessage(payload, IFRAME_ORIGIN);
      }

      /**
       * Your backend owns this endpoint. It should call:
       * POST https://alterproduct.com/public-api/v1/embed/session
       * using server-side Alter Product API credentials.
       */
      async function createEmbedSessionFromYourBackend(payload) {
        const res = await fetch("/api/alter/embed-session", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(payload || {})
        });

        if (!res.ok) throw new Error("Failed to create embed session");
        const data = await res.json();

        // Expected response: { token: "..." }
        if (!data || !data.token) throw new Error("Missing token");
        return data.token;
      }

      window.addEventListener("message", async (event) => {
        // ✅ 1) Always validate origin
        if (event.origin !== IFRAME_ORIGIN) return;

        // ✅ 2) Always validate source
        if (event.source !== iframe.contentWindow) return;

        const msg = event.data || {};

        // -----------------------
        // A) HANDSHAKE
        // iframe -> parent: ALTER_CHILD_HELLO { nonce }
        // parent -> iframe: ALTER_PARENT_ACK  { nonce }
        // -----------------------
        if (msg.type === "ALTER_CHILD_HELLO") {
          if (!msg.nonce || typeof msg.nonce !== "string") return;

          handshakeNonce = msg.nonce;
          handshakeOk = true;

          postToIframe({ type: "ALTER_PARENT_ACK", nonce: handshakeNonce });
          return;
        }

        // Ignore everything until handshake is done
        if (!handshakeOk) return;

        // -----------------------
        // B) TOKEN REQUEST (on-demand)
        // iframe -> parent: ALTER_TOOL_INIT_SESSION
        //   payload: { tool, mode, uiDesignId }
        //
        // parent -> iframe: ALTER_TOOL_SESSION_READY
        //   { token }
        // -----------------------
        if (msg.type === "ALTER_TOOL_INIT_SESSION") {
          try {
            const payload = msg.payload || {};

            const tool = String(payload.tool || TOOL).toLowerCase();
            const designId = Number(payload.uiDesignId || DESIGN_ID);

            const token = await createEmbedSessionFromYourBackend({
              tool,
              designId,
              origin: window.location.origin
            });

            postToIframe({
              type: "ALTER_TOOL_SESSION_READY",
              token
            });
          } catch (e) {
            postToIframe({
              type: "ALTER_TOOL_SESSION_ERROR",
              message: String(e && e.message ? e.message : e)
            });
          }
          return;
        }

        // -----------------------
        // C) OPTIONAL: listen to tool events (examples)
        // -----------------------
        if (msg.type === "ALTER_VIEWER_ADD_TO_CART") {
          console.log("[Alter] Add to cart:", msg.payload);
          return;
        }
      });
    </script>
  </body>
</html>

Stilizare de bază

Poți personaliza Viewer în două moduri:

  • Prin parametri URL – configurează fundalul, mediul, iluminarea, navigarea, vizibilitatea Adaugă în coș și preselectarea variantelor (vezi Stilizare (parametri URL)).
  • Prin CSS pe containerul din jurul iframe-ului (dimensiuni, borduri, rază și aranjament).
#wrapper {
  height: 320px;
  width: 400px;
  overflow: hidden;
  border-radius: 14px;
  background: linear-gradient(0deg, rgba(0,43,133,1) 0%, rgba(0,182,215,1) 100%);
}

iframe {
  width: 100%;
  height: 100%;
  display: block;
  border: 0;
}