wichat
חזרה לאפליקציה ←

מדריך הטמעה למפתחים

כל מה שצריך כדי להטמיע את סוכן ה-AI של wichat באתר שלך - בכל פלטפורמה, בכל תרחיש, עם דוגמאות קוד מלאות ומוכנות להעתקה.

נקודת ההתחלה. שורת ההטמעה הבסיסית שמפעילה את הווידג'ט היא: <script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>
החליפו את YOUR_KEY במפתח הייחודי של העסק שלכם (זמין במסך "הטמעה" בדאשבורד). הווידג'ט חושף API מלא למפתחים שמעוניינים בשליטה מלאה בווידג׳ט מתוך קוד האתר בנוסף לפאנל הניהול אצלנו - window.wichat (destroy, startAnimation, isReady, isOpen, open, close, hide, show, toggle, sendMessage, pendingMessage, setContext, updateConfig, resetConfig) - פירוט מלא בסעיף ה-API.

1HTML (אתר סטטי)

אתר רגיל ללא Framework - קבצי HTML נפרדים לכל דף.

כל הדפיםבכל קובץ HTML, לפני </body>

הדביקו את השורה בכל דף שבו רוצים את הווידג'ט (או בקובץ תבנית/footer משותף אם יש).

<!doctype html>
<html>
<head>...</head>
<body>
  <!-- התוכן של הדף -->

  <!-- wichat AI Widget -->
  <script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>
</body>
</html>
דף ספציפי בלבדcontact.html

מוסיפים את השורה רק בקובץ של הדף הרצוי (למשל דף צור קשר) - ולא בשאר הדפים.

<!-- רק בקובץ contact.html -->
<script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>
טעינה מושהית / לפי אינטראקציהכל דף

לשיפור ביצועים ניתן לטעון את הווידג'ט רק אחרי שהדף נטען במלואו, אחרי השהיה, או בגלילה ראשונה.

<script>
  function loadWichat() {
    if (window.__wichatLoaded) return;
    window.__wichatLoaded = true;
    var s = document.createElement('script');
    s.src = 'https://wichat.ai/widget.js';
    s.setAttribute('data-key', 'YOUR_KEY');
    document.body.appendChild(s);
  }

  // אפשרות א': 3 שניות אחרי טעינת הדף
  window.addEventListener('load', function () {
    setTimeout(loadWichat, 3000);
  });

  // אפשרות ב': בגלילה או במגע ראשון (מבטל את הטיימר)
  window.addEventListener('scroll', loadWichat, { once: true });
  window.addEventListener('touchstart', loadWichat, { once: true });
</script>

חשוב: כשטוענים דינמית, חובה להוסיף את data-key באמצעות setAttribute - בלעדיו הווידג'ט לא יעלה.

הסרה ידנית

להסרה מלאה של הווידג'ט בזמן ריצה (למשל בכניסה לאזור אישי):

if (window.wichat) {
  window.wichat.destroy(); // מסיר את הכפתור, החלון, המאזינים והטיימרים
}

2React (SPA)

אפליקציית React עם Vite / CRA / React Router. הווידג'ט מזהה לבד הסרה של תגית הסקריפט ומנקה את עצמו, אבל מומלץ לקרוא ל-destroy() במפורש ב-cleanup.

כל הדפיםindex.html

הדרך הפשוטה ביותר: מוסיפים את הסקריפט פעם אחת ב-index.html. ב-SPA כל ה"דפים" חיים באותו קובץ HTML, אז הווידג'ט יופיע בכולם.

<!-- index.html -->
<body>
  <div id="root"></div>
  <script type="module" src="/src/main.jsx"></script>

  <!-- wichat AI Widget -->
  <script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>
</body>
כל הדפים (דרך קומפוננטה)src/App.jsx

אם אתם מעדיפים לשלוט בזה מתוך React (למשל להציג רק למשתמשים לא מחוברים):

import { useEffect } from 'react';

function wichatWidget() {
  useEffect(() => {
    const script = document.createElement('script');
    script.src = 'https://wichat.ai/widget.js';
    script.setAttribute('data-key', 'YOUR_KEY');
    document.body.appendChild(script);

    return () => {
      if (window.wichat) window.wichat.destroy();
      script.remove();
    };
  }, []);

  return null;
}

export default function App() {
  return (
    <>
      {/* ...הראוטר והדפים שלכם... */}
      <wichatWidget />
    </>
  );
}
דף ספציפי בלבדsrc/pages/Contact.jsx

מרנדרים את הקומפוננטה רק בדף הרצוי. ה-cleanup ב-useEffect מבטיח שהווידג'ט ייעלם כשעוזבים את הדף.

import { useEffect } from 'react';

export default function Contact() {
  useEffect(() => {
    const script = document.createElement('script');
    script.src = 'https://wichat.ai/widget.js';
    script.setAttribute('data-key', 'YOUR_KEY');
    document.body.appendChild(script);

    return () => {
      if (window.wichat) window.wichat.destroy();
      script.remove();
    };
  }, []);

  return <div>צור קשר</div>;
}
Hook לשימוש חוזרsrc/hooks/useWichat.js

אם צריך את הווידג'ט בכמה דפים (אך לא בכולם) - Hook קטן חוסך כפילויות:

// src/hooks/useWichat.js
import { useEffect } from 'react';

export function useWichat(key) {
  useEffect(() => {
    const script = document.createElement('script');
    script.src = 'https://wichat.ai/widget.js';
    script.setAttribute('data-key', key);
    document.body.appendChild(script);

    return () => {
      if (window.wichat) window.wichat.destroy();
      script.remove();
    };
  }, [key]);
}

// שימוש בכל דף רצוי:
// useWichat('YOUR_KEY');
הסתרה בדפים מסוימים (React Router)src/App.jsx

להציג בכל האתר חוץ מנתיבים מסוימים (למשל אזור ניהול):

import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';

const HIDDEN_PATHS = ['/admin', '/checkout'];

function wichatWidget() {
  const { pathname } = useLocation();
  const hidden = HIDDEN_PATHS.some((p) => pathname.startsWith(p));

  useEffect(() => {
    if (hidden) return;
    const script = document.createElement('script');
    script.src = 'https://wichat.ai/widget.js';
    script.setAttribute('data-key', 'YOUR_KEY');
    document.body.appendChild(script);
    return () => {
      if (window.wichat) window.wichat.destroy();
      script.remove();
    };
  }, [hidden]);

  return null;
}

3Next.js

ב-Next.js משתמשים בקומפוננטת next/script המובנית. דוגמאות ל-App Router (גרסה 13+) ול-Pages Router.

כל הדפים - App Routerapp/layout.tsx
import Script from 'next/script';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="he" dir="rtl">
      <body>
        {children}
        <Script
          src="https://wichat.ai/widget.js"
          data-key="YOUR_KEY"
          strategy="afterInteractive"
        />
      </body>
    </html>
  );
}

strategy="afterInteractive" טוען את הווידג'ט אחרי שהדף אינטראקטיבי; אפשר גם lazyOnload לטעינה עצלה יותר.

דף ספציפי - App Routerapp/contact/page.tsx

מוסיפים את ה-Script רק בדף הרצוי. מכיוון ש-Next שומר סקריפטים בין ניווטים, מומלץ לעטוף בקומפוננטת Client עם ניקוי:

'use client';

import { useEffect } from 'react';

function wichatOnThisPage() {
  useEffect(() => {
    const script = document.createElement('script');
    script.src = 'https://wichat.ai/widget.js';
    script.setAttribute('data-key', 'YOUR_KEY');
    document.body.appendChild(script);

    return () => {
      if ((window as any).wichat) (window as any).wichat.destroy();
      script.remove();
    };
  }, []);

  return null;
}

export default function ContactPage() {
  return (
    <main>
      <h1>צור קשר</h1>
      <wichatOnThisPage />
    </main>
  );
}
כל הדפים - Pages Routerpages/_app.tsx
import type { AppProps } from 'next/app';
import Script from 'next/script';

export default function MyApp({ Component, pageProps }: AppProps) {
  return (
    <>
      <Component {...pageProps} />
      <Script
        src="https://wichat.ai/widget.js"
        data-key="YOUR_KEY"
        strategy="afterInteractive"
      />
    </>
  );
}
דף ספציפי - Pages Routerpages/contact.tsx
import { useEffect } from 'react';

export default function Contact() {
  useEffect(() => {
    const script = document.createElement('script');
    script.src = 'https://wichat.ai/widget.js';
    script.setAttribute('data-key', 'YOUR_KEY');
    document.body.appendChild(script);

    return () => {
      if ((window as any).wichat) (window as any).wichat.destroy();
      script.remove();
    };
  }, []);

  return <h1>צור קשר</h1>;
}

4Vue 3

אפליקציית Vue עם Vite ו-Vue Router.

כל הדפיםindex.html
<!-- index.html -->
<body>
  <div id="app"></div>
  <script type="module" src="/src/main.js"></script>

  <!-- wichat AI Widget -->
  <script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>
</body>
דף ספציפי בלבדsrc/views/ContactView.vue
<script setup>
import { onMounted, onUnmounted } from 'vue';

let script;

onMounted(() => {
  script = document.createElement('script');
  script.src = 'https://wichat.ai/widget.js';
  script.setAttribute('data-key', 'YOUR_KEY');
  document.body.appendChild(script);
});

onUnmounted(() => {
  if (window.wichat) window.wichat.destroy();
  script?.remove();
});
</script>

<template>
  <div>צור קשר</div>
</template>
Composable לשימוש חוזרsrc/composables/useWichat.js
// src/composables/useWichat.js
import { onMounted, onUnmounted } from 'vue';

export function useWichat(key) {
  let script;
  onMounted(() => {
    script = document.createElement('script');
    script.src = 'https://wichat.ai/widget.js';
    script.setAttribute('data-key', key);
    document.body.appendChild(script);
  });
  onUnmounted(() => {
    if (window.wichat) window.wichat.destroy();
    script?.remove();
  });
}

// שימוש בכל View רצוי:
// useWichat('YOUR_KEY');

5Nuxt 3

כל הדפיםnuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      script: [
        {
          src: 'https://wichat.ai/widget.js',
          'data-key': 'YOUR_KEY',
          tagPosition: 'bodyClose',
        },
      ],
    },
  },
});
דף ספציפי בלבדpages/contact.vue
<script setup>
let script;

onMounted(() => {
  script = document.createElement('script');
  script.src = 'https://wichat.ai/widget.js';
  script.setAttribute('data-key', 'YOUR_KEY');
  document.body.appendChild(script);
});

onUnmounted(() => {
  if (window.wichat) window.wichat.destroy();
  script?.remove();
});
</script>

<template>
  <div>צור קשר</div>
</template>

הקוד רץ רק בדפדפן (onMounted לא רץ ב-SSR), כך שאין צורך בבדיקת process.client.

6Angular

כל הדפיםsrc/index.html
<!-- src/index.html -->
<body>
  <app-root></app-root>

  <!-- wichat AI Widget -->
  <script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>
</body>
דף ספציפי בלבדcontact.component.ts
import { Component, OnDestroy, OnInit } from '@angular/core';

declare global {
  interface Window { wichat?: { destroy: () => void } }
}

@Component({
  selector: 'app-contact',
  standalone: true,
  template: `<h1>צור קשר</h1>`,
})
export class ContactComponent implements OnInit, OnDestroy {
  private script?: HTMLScriptElement;

  ngOnInit(): void {
    this.script = document.createElement('script');
    this.script.src = 'https://wichat.ai/widget.js';
    this.script.setAttribute('data-key', 'YOUR_KEY');
    document.body.appendChild(this.script);
  }

  ngOnDestroy(): void {
    window.wichat?.destroy();
    this.script?.remove();
  }
}
Service לשימוש חוזרwichat.service.ts
import { Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class wichatService {
  private script?: HTMLScriptElement;

  load(key: string): void {
    if (this.script) return; // כבר טעון
    this.script = document.createElement('script');
    this.script.src = 'https://wichat.ai/widget.js';
    this.script.setAttribute('data-key', key);
    document.body.appendChild(this.script);
  }

  unload(): void {
    (window as any).wichat?.destroy();
    this.script?.remove();
    this.script = undefined;
  }
}

7Svelte / SvelteKit

כל הדפים - SvelteKitsrc/app.html
<!-- src/app.html -->
<body data-sveltekit-preload-data="hover">
  <div style="display: contents">%sveltekit.body%</div>

  <!-- wichat AI Widget -->
  <script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>
</body>
דף ספציפי בלבדsrc/routes/contact/+page.svelte
<script>
  import { onMount } from 'svelte';

  onMount(() => {
    const script = document.createElement('script');
    script.src = 'https://wichat.ai/widget.js';
    script.setAttribute('data-key', 'YOUR_KEY');
    document.body.appendChild(script);

    // הפונקציה שמוחזרת מ-onMount רצה כשעוזבים את הדף
    return () => {
      if (window.wichat) window.wichat.destroy();
      script.remove();
    };
  });
</script>

<h1>צור קשר</h1>

8Vite (Vanilla JS/TS)

פרויקט Vite ללא Framework. אם אתם משתמשים ב-Vite עם React/Vue/Svelte - ראו את הסעיף של ה-Framework הרלוונטי.

כל הדפיםindex.html
<!-- index.html -->
<body>
  <div id="app"></div>
  <script type="module" src="/src/main.js"></script>

  <!-- wichat AI Widget -->
  <script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>
</body>

ב-Multi-Page App של Vite (כמה קבצי HTML) - הוסיפו את השורה בכל קובץ HTML רצוי, או רק בדף הספציפי.

טעינה דינמית מתוך הקודsrc/main.js
function loadWichat(key) {
  const script = document.createElement('script');
  script.src = 'https://wichat.ai/widget.js';
  script.setAttribute('data-key', key);
  document.body.appendChild(script);
  return () => {
    if (window.wichat) window.wichat.destroy();
    script.remove();
  };
}

// טעינה:
const unloadWichat = loadWichat('YOUR_KEY');

// הסרה בהמשך (אם צריך):
// unloadWichat();

9Google Tag Manager

אם יש לכם GTM באתר - אפשר להטמיע את הווידג'ט בלי לגעת בקוד האתר בכלל. עובד על כל פלטפורמה.

כל הדפים
<script>
  (function () {
    var s = document.createElement('script');
    s.src = 'https://wichat.ai/widget.js';
    s.setAttribute('data-key', 'YOUR_KEY');
    document.body.appendChild(s);
  })();
</script>

חשוב: ב-Custom HTML של GTM אי אפשר להשתמש ב-src ישירות עם data-attribute, לכן טוענים דינמית כמו בדוגמה.

דף ספציפי בלבד

באתרי SPA כדאי להשתמש ב-Trigger מסוג History Change ולהוסיף גם Tag של הסרה (window.wichat && window.wichat.destroy()) ביציאה מהנתיב.

10WordPress

שלוש דרכים: קוד ב-functions.php (למפתחים), תוסף Code Snippets (מומלץ למשתמשים), או ידנית בתבנית.

כל הדפיםfunctions.php (של Child Theme)
<?php
// wichat AI Widget - כל הדפים
function wichat_widget_script() {
  ?>
  <script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>
  <?php
}
add_action('wp_footer', 'wichat_widget_script');

מומלץ להשתמש ב-Child Theme כדי שהקוד לא יימחק בעדכון תבנית. לחלופין: תוסף WPCode / Code Snippets ← Snippet חדש מסוג HTML ← מיקום Footer.

דף ספציפי בלבדfunctions.php

שימוש ב-Conditional Tags של WordPress - לפי slug, מזהה דף, או סוג תוכן:

<?php
function wichat_widget_script() {
  // רק בדף עם ה-slug "contact"
  if (!is_page('contact')) return;

  // דוגמאות נוספות:
  // if (!is_front_page()) return;          // רק דף הבית
  // if (!is_page(array(12, 'about'))) return; // לפי ID או כמה דפים
  // if (!is_singular('product')) return;   // רק דפי מוצר (WooCommerce)
  ?>
  <script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>
  <?php
}
add_action('wp_footer', 'wichat_widget_script');
כל הדפים חוץ מדפים מסוימיםfunctions.php
<?php
function wichat_widget_script() {
  // לא להציג בעגלה ובקופה
  if (is_page(array('cart', 'checkout'))) return;
  ?>
  <script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>
  <?php
}
add_action('wp_footer', 'wichat_widget_script');

11Elementor (WordPress)

כל הדפים
<script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>
דף ספציפי בלבד
<script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>

12Shopify

כל הדפיםlayout/theme.liquid
    <!-- wichat AI Widget -->
    <script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>
  </body>
</html>
דף/תבנית ספציפית בלבדlayout/theme.liquid

שימוש בתנאי Liquid לפי סוג התבנית או ה-handle של הדף:

    {% comment %} רק בדף צור קשר {% endcomment %}
    {% if page.handle == 'contact' %}
      <script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>
    {% endif %}

    {% comment %} דוגמאות נוספות:
      {% if template == 'index' %}          - רק דף הבית
      {% if template contains 'product' %}  - רק דפי מוצר
      {% if template contains 'collection' %} - רק דפי קטגוריה
    {% endcomment %}
  </body>
בכל החנות חוץ מהקופה

דפי ה-Checkout של Shopify לא מריצים קוד מהתבנית (אלא ב-Shopify Plus), כך שהווידג'ט ממילא לא יופיע שם. להסתרה גם בעגלה:

    {% unless template contains 'cart' %}
      <script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>
    {% endunless %}
  </body>

13Wix

ב-Wix מטמיעים דרך ממשק הניהול - בלי לגעת בקוד האתר. נדרשת תוכנית Premium עם דומיין מחובר.

כל הדפים
<script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>

בחירת "Load code once" חשובה - Wix הוא SPA, וכך הסקריפט לא ייטען מחדש בכל מעבר דף. הווידג'ט יישאר זמין בכל האתר.

דף ספציפי בלבד
<script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>

Wix מסיר את הסקריפט אוטומטית במעבר לדף אחר - הווידג'ט מזהה זאת ומנקה את עצמו לבד (MutationObserver מובנה). אין צורך בקוד נוסף.

14Webflow

נדרשת תוכנית בתשלום (Site Plan) כדי להוסיף Custom Code.

כל הדפים
<!-- wichat AI Widget -->
<script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>
דף ספציפי בלבד
<script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>

קוד ברמת הדף נטען רק בדף הזה - אין צורך בניקוי ידני, כי כל ניווט ב-Webflow טוען דף חדש.

15Squarespace

נדרשת תוכנית Business ומעלה (Code Injection זמין רק בתוכניות בתשלום).

כל הדפים
<!-- wichat AI Widget -->
<script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>
דף ספציפי בלבד
<script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>

חלופה ללא Code Injection: הוסיפו לדף בלוק מסוג Code (בעורך התוכן) והדביקו בו את אותה שורה.

16Framer

כל הדפים
<script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>
דף ספציפי בלבד

ב-Framer אין הזרקת קוד לדף בודד, אבל אפשר להתנות לפי נתיב ה-URL:

<script>
  (function () {
    // רשימת הנתיבים שבהם הווידג'ט יופיע
    var ALLOWED = ['/contact', '/pricing'];

    function syncWichat() {
      var allowed = ALLOWED.indexOf(window.location.pathname) > -1;
      var loaded = !!window.wichat;
      if (allowed && !loaded) {
        var s = document.createElement('script');
        s.src = 'https://wichat.ai/widget.js';
        s.setAttribute('data-key', 'YOUR_KEY');
        document.body.appendChild(s);
      } else if (!allowed && loaded) {
        window.wichat.destroy();
      }
    }

    // Framer הוא SPA - מאזינים לשינויי ניווט
    var push = history.pushState;
    history.pushState = function () {
      push.apply(this, arguments);
      setTimeout(syncWichat, 0);
    };
    window.addEventListener('popstate', syncWichat);
    syncWichat();
  })();
</script>

הדוגמה הזו (טעינה/הסרה לפי נתיב עם האזנה ל-History) עובדת בכל אתר SPA שבו יש רק נקודת הזרקה גלובלית אחת.

17Flutter Web

בפרויקט Flutter Web, הווידג'ט מוטמע בקובץ ה-HTML המארח - הוא מרחף מעל אזור הציור של Flutter ולא מתנגש איתו.

כל האפליקציהweb/index.html
<!-- web/index.html -->
<body>
  <script src="flutter_bootstrap.js" async></script>

  <!-- wichat AI Widget -->
  <script src="https://wichat.ai/widget.js" data-key="YOUR_KEY"></script>
</body>

הווידג'ט מצויר ב-DOM מעל ה-canvas של Flutter (z-index גבוה), ולכן זמין מכל מסך באפליקציה.

מסך ספציפי בלבדlib/wichat.dart

שליטה מתוך Dart באמצעות JS interop - טעינה כשנכנסים למסך והסרה כשעוזבים:

// lib/wichat.dart
import 'dart:js_interop';
import 'package:web/web.dart' as web;

void loadWichat(String key) {
  if (web.document.getElementById('wichat-script') != null) return;
  final script = web.document.createElement('script') as web.HTMLScriptElement
    ..id = 'wichat-script'
    ..src = 'https://wichat.ai/widget.js';
  script.setAttribute('data-key', key);
  web.document.body!.appendChild(script);
}

void destroyWichat() {
  // הסרת תגית הסקריפט מפעילה את הניקוי האוטומטי של הווידג'ט
  web.document.getElementById('wichat-script')?.remove();
}
// שימוש במסך (StatefulWidget):
class ContactScreen extends StatefulWidget {
  const ContactScreen({super.key});
  @override
  State<ContactScreen> createState() => _ContactScreenState();
}

class _ContactScreenState extends State<ContactScreen> {
  @override
  void initState() {
    super.initState();
    loadWichat('YOUR_KEY');
  }

  @override
  void dispose() {
    destroyWichat();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) => const Scaffold(
        body: Center(child: Text('צור קשר')),
      );
}

הווידג'ט כולל MutationObserver שמזהה את הסרת תגית הסקריפט ומנקה את עצמו אוטומטית - לכן מספיק להסיר את התגית.

18API Reference

הממשק שהווידג'ט חושף למפתחים ותכונות ההתנהגות המובנות שלו.

תגית הסקריפט
מאפייןחובהתיאור
srcכןhttps://wichat.ai/widget.js - כתובת הסקריפט. ה-API נגזר ממנה אוטומטית.
data-keyכןהמפתח הייחודי של העסק. בלעדיו הווידג'ט לא ייטען (שגיאה ב-Console).
window.wichat.isReady()

מחזירה true או false - האם הווידג'ט סיים את הטעינה הראשונה שלו בכניסה לאתר/למסך: כלומר קיבל את כל ה-config שלו מהשרת שלנו וסיים להתרנדר. מומלץ לבדוק אותה לפני כל שימוש בכל אחת מפונקציות ה-API האחרות - כך מבטיחים שלא תהיה שגיאת timing כשקוראים לפונקציה לפני שהווידג'ט מוכן.

// דוגמה בסיסית: פתיחת הצ'אט רק אם הווידג'ט מוכן
if (window.wichat) {
  if (window.wichat.isReady() === true) {
    window.wichat.open();
  }
}

// דוגמה: המתנה עד שהווידג'ט מוכן (בדיקה חוזרת קצרה)
function whenWichatReady(cb) {
  if (window.wichat && window.wichat.isReady()) return cb();
  setTimeout(function () { whenWichatReady(cb); }, 200);
}
whenWichatReady(function () {
  window.wichat.sendMessage('שלום, אשמח לעזרה');
});
מצבערך מוחזר
הווידג'ט קיבל את ה-config מהשרת וסיים את הרינדור הראשוןtrue
הסקריפט נטען אבל ה-config עדיין בטעינהfalse
הווידג'ט הוסר עם destroy()false
window.wichat.isOpen()

מחזירה true או false - האם חלון הצ'אט פתוח כרגע על המסך. true כאשר הצ'אט פתוח, false כאשר הוא סגור. שימושי כדי לסנכרן אלמנטים באתר שלכם עם מצב הצ'אט (למשל להסתיר כפתור צף משלכם כל עוד הצ'אט פתוח).

// דוגמה: כפתור באתר שמתנהג לפי מצב הצ'אט
document.getElementById('chat-btn').addEventListener('click', function () {
  if (!window.wichat || !window.wichat.isReady()) return;

  if (window.wichat.isOpen() === true) {
    window.wichat.close();   // פתוח - נסגור
  } else {
    window.wichat.open();    // סגור - נפתח
  }
});

// דוגמה: הסתרת כפתור צף משלכם כל עוד הצ'אט פתוח
setInterval(function () {
  if (!window.wichat || !window.wichat.isReady()) return;
  var myFab = document.getElementById('my-fab');
  myFab.style.display = window.wichat.isOpen() ? 'none' : 'flex';
}, 500);
מצבערך מוחזר
חלון הצ'אט פתוח (המבקר לחץ על הכפתור או נקראה open())true
חלון הצ'אט סגורfalse
הווידג'ט הוסתר עם hide() (החלון נסגר אוטומטית)false
הווידג'ט עדיין בטעינה או הוסר עם destroy()false
window.wichat.startAnimation()Pro / Premium / Partner

מפעילה מחדש את אנימציית הפתיחה של הווידג'ט - אותה דמות מונפשת שמופיעה בכניסה לאתר ומתמזגת בחזרה לאייקון הווידג'ט. שימושי כאשר רוצים שלחיצה על כפתור מסוים באתר שלכם (או אירוע אחר בדף) תפעיל את האנימציה שוב, ללא תלות בהגדרת התדירות שנבחרה בפאנל.

אנימציות פתיחה זמינות למנויי Pro, Premium ו-Partner בלבד, והן גם אינן שדה חובה בהגדרות העסק. לכן אם המנוי אינו אחד מהשלושה, או שלא נבחרה אנימציית פתיחה לעסק - הפונקציה פשוט לא תעשה דבר ותרשום אזהרה ב-Console (ללא שגיאה ובלי לשבור את הדף).

// דוגמה: כפתור באתר שמפעיל מחדש את אנימציית הפתיחה
document.getElementById('replay-anim').addEventListener('click', function () {
  if (window.wichat && window.wichat.isReady()) {
    window.wichat.startAnimation();
  }
});

// דוגמה: הפעלת האנימציה כשהמבקר מגיע לסקשן "צור קשר"
var contact = document.getElementById('contact');
var seen = false;
new IntersectionObserver(function (entries) {
  if (seen || !entries[0].isIntersecting) return;
  if (!window.wichat || !window.wichat.isReady()) return;
  seen = true;
  window.wichat.startAnimation();
}, { threshold: 0.5 }).observe(contact);
מצבהתנהגות
המנוי הוא Pro / Premium / Partner ונבחרה אנימציית פתיחההאנימציה מתנגנת מחדש מההתחלה ומתמזגת בחזרה לאייקון הווידג'ט.
המנוי אינו Pro / Premium / Partnerלא מתבצע דבר. אזהרה ב-Console: entrance animations are available on the Pro, Premium and Partner plans only
לא הוגדרה אנימציית פתיחה לעסקלא מתבצע דבר. אזהרה ב-Console: no entrance animation is configured for this business
הווידג'ט מוסתר עם hide()לא מתבצע דבר. אזהרה ב-Console - יש לקרוא ל-show() קודם.
הווידג'ט עדיין בטעינהלא מתבצע דבר. אזהרה ב-Console - מומלץ לבדוק isReady() לפני הקריאה.

אין צורך לחכות לסיום האנימציה - היא מנוגנת מעל הדף ומסתיימת מעצמה, וכפתור הווידג'ט חוזר להיות לחיץ בסופה.

window.wichat.destroy()

מסיר את הווידג'ט לחלוטין: כפתור, חלון צ'אט, מאזיני אירועים, טיימרים ו-Observers. בטוח לקריאה חוזרת (no-op אחרי הפעם הראשונה).

// דוגמה: הסרה בטוחה מכל מקום בקוד
if (window.wichat) {
  window.wichat.destroy();
}
התנהגותפירוט
ניקוי אוטומטיהווידג'ט עוקב (MutationObserver) אחרי תגית ה-<script> שלו. אם היא מוסרת מה-DOM (נפוץ בניווטי SPA) - הוא הורס את עצמו אוטומטית.
קריאה חוזרתdestroy() אידמפוטנטית - קריאות נוספות לא זורקות שגיאה.
טעינה מחדשאחרי destroy, הזרקה חדשה של תגית הסקריפט טוענת מופע נקי לגמרי.
זיכרון שיחההשיחה נשמרת ב-localStorage של הדפדפן - destroy לא מוחק אותה; המבקר ימשיך את אותה שיחה בטעינה הבאה.
window.wichat.open()

פותח את חלון הצ'אט אוטומטית, בלי שהמבקר יצטרך ללחוץ על כפתור הווידג'ט. אם החלון כבר פתוח - לא קורה כלום (בטוח לקריאה חוזרת). שימושי למשל כשעוברים למסך מסוים ורוצים שהצ'אט ייפתח מיד.

// דוגמה: פתיחת הצ'אט אוטומטית כשנכנסים לדף "צור קשר"
if (window.wichat) {
  window.wichat.open();
}

// דוגמה ב-React: פתיחה אוטומטית במעבר למסך
useEffect(() => {
  if (window.wichat) window.wichat.open();
}, []);
window.wichat.close()

סוגר את חלון הצ'אט אוטומטית - הפעולה ההפוכה ל-open(). הפונקציה בודקת בעצמה אם החלון פתוח: אם הוא כבר סגור - לא קורה כלום ולא נזרקת שגיאה.

// דוגמה: סגירת הצ'אט כשעוזבים מסך מסוים
if (window.wichat) {
  window.wichat.close();
}
window.wichat.toggle()

פונקציית ביניים בין open() ל-close(): אם הצ'אט פתוח - היא סוגרת אותו; אם הוא סגור - היא פותחת. שימושי לכפתור "צ'אט" משלכם באתר.

// דוגמה: כפתור באתר שפותח/סוגר את הצ'אט
<button onclick="window.wichat && window.wichat.toggle()">
  דברו איתנו
</button>
window.wichat.sendMessage(text)

שולח הודעה לצ'אט בשם המבקר, אוטומטית: אם הצ'אט סגור - הוא נפתח קודם (אם כבר פתוח - נשאר כמו שהוא), ההודעה שהעברתם מודבקת לשדה הקלט ונשלחת מיד לסוכן, והסוכן עונה כרגיל. שימושי לכפתורים באתר שמתחילים שיחה על נושא ספציפי.

// דוגמה: כפתור "בדקו זמינות" שפותח את הצ'אט ושואל את הסוכן
<button onclick="window.wichat && window.wichat.sendMessage('היי, אני רוצה לבדוק זמינות לתור השבוע')">
  בדקו זמינות
</button>

// דוגמה: שאלה על מוצר מתוך דף מוצר
document.getElementById('ask-btn').addEventListener('click', function () {
  if (window.wichat) {
    window.wichat.sendMessage('אשמח לפרטים נוספים על המוצר בדף הזה');
  }
});

ההודעה נספרת במכסת ההודעות של השיחה כמו הודעה רגילה שהמבקר מקליד. טקסט ריק או ערך שאינו מחרוזת - נדחה עם אזהרה ב-Console (ללא שגיאה).

window.wichat.setContext({ page, context })

הקשר מסך עבור ה-AI. מגדירה לסוכן מה המשתמש רואה כרגע על המסך באתר שלכם. כך במקום שהמבקר יצטרך לכתוב "יש את האייפון 17 פרו 256GB בצבע שחור במלאי?" הוא יוכל לכתוב פשוט "יש את זה במלאי?" - והסוכן יבין בדיוק על מה מדובר.

איך זה עובד: הקריאה לפונקציה שומרת את המידע בזיכרון מקומי בדפדפן בלבד - שום דבר לא נשלח לשרת שלנו. רק כשהמבקר שולח הודעה בצ'אט, ההקשר העדכני ביותר מצורף להודעה ונשלח ל-AI יחד איתה. ה-AI מקבל הסבר שהמידע הזה מתאר את המסך שהמשתמש רואה כרגע, ומתייחס אליו רק כשהוא רלוונטי לשאלה. קיים "מקום" אחד בלבד להקשר: כל קריאה חדשה ל-setContext מחליפה את הקודמת ומוחקת אותה מהזיכרון המקומי, כך שתמיד נקלט רק ההקשר העדכני ביותר.

מבחינת ארכיטקטורה, הפונקציה חייבת להיות מוגדרת באתר שלכם בצורה הזו במדויק - page (מחרוזת - שם המסך בטקסט חופשי) ו-context (אובייקט JSON רגיל ותקין עם כמה שדות שרוצים):

window.wichat.setContext({
  page: "",
  context: {
  }
});

דוגמה בדף מוצר:

window.wichat.setContext({
  page: "product",
  context: {
    id: "123",
    name: "iPhone 17 Pro 256gb black",
    price: 4999,
    in_stock: true
  }
});

// עכשיו המבקר יכול לשאול בצ'אט: "יש את זה במלאי?"
// והסוכן יבין שמדובר ב-iPhone 17 Pro 256gb black.

דוגמה ב-React - עדכון ההקשר בכל מעבר בין מוצרים/מסכים:

useEffect(() => {
  if (window.wichat && window.wichat.isReady()) {
    window.wichat.setContext({
      page: "product",
      context: { id: product.id, name: product.name, price: product.price }
    });
  }
}, [product]);
שדהדרישה
pageחובה. מחרוזת - שם המסך בטקסט חופשי (למשל "product", "checkout", "עמוד הבית").
contextחובה. אובייקט JSON רגיל ותקין - כמה שדות שרוצים (עד 2000 תווים כ-JSON).
התנהגותפירוט
שמירה מקומית בלבדהקריאה לא שולחת שום דבר לשרת - המידע נשמר בזיכרון הדף בלבד.
הקשר אחד בלבדהגדרה חדשה מחליפה את הקודמת - רק ההקשר העדכני ביותר נקלט בהודעת המבקר.
שליחה ל-AIההקשר מצורף להודעת המבקר ונשלח יחד איתה בבקשה אחת בלבד - חוסך קרדיטים ומאפשר ל-AI להבין בצורה הטובה ביותר.
מבנה לא תקיןאזהרה ב-Console וההקשר לא נשמר (ללא שגיאה, הווידג'ט ממשיך לעבוד כרגיל).
ניקוירענון דף או destroy() מוחקים את ההקשר מהזיכרון.

מומלץ: אם משתמשים ב-setContext במסך מסוים באתר שלכם - כדאי כבר להוסיף אותה לכל המסכים באתר. כך בכל מעבר מסך ההקשר מתעדכן, וה-AI מקבל תמיד את ההקשר העדכני ביותר של המסך שבו המבקר נמצא בעת שליחת ההודעה - ולא הקשר ישן ממסך קודם.

window.wichat.pendingMessage(text)

זהה כמעט לגמרי ל-sendMessage(text), בהבדל אחד: ההודעה לא נשלחת לסוכן. אם הצ'אט סגור - הוא נפתח קודם (אם כבר פתוח - נשאר כמו שהוא), וההודעה שהעברתם מודבקת לשדה הקלט ומחכה שם. המבקר צריך ללחוץ בעצמו על כפתור השליחה (או Enter) כדי שההודעה תישלח. שימושי כשרוצים להציע למבקר שאלה מוכנה, אבל להשאיר לו את ההחלטה ואפשרות לערוך אותה לפני השליחה.

// דוגמה: כפתור שמכין למבקר שאלה מוכנה בשדה הקלט (בלי לשלוח)
<button onclick="window.wichat && window.wichat.pendingMessage('היי, אני רוצה לבדוק זמינות לתור השבוע')">
  שאלו על זמינות
</button>

// דוגמה: הכנת שאלה על מוצר מתוך דף מוצר
document.getElementById('ask-btn').addEventListener('click', function () {
  if (window.wichat) {
    window.wichat.pendingMessage('יש לי שאלה על ' + productName);
  }
});
התנהגותפירוט
לא נשלח לסוכןהטקסט רק מודבק לשדה הקלט. אין קריאה לשרת ולא נצרכת הודעה מהמכסה עד שהמבקר שולח בעצמו.
פתיחת הצ'אטאם הצ'אט סגור הוא נפתח, והפוקוס עובר לשדה הקלט כדי שהמבקר יוכל לערוך ולשלוח.
קריאה חוזרתקריאה נוספת מחליפה את הטקסט שנמצא בשדה הקלט.
טקסט לא תקיןערך שאינו מחרוזת, או מחרוזת ריקה, מדולג עם אזהרה ב-Console - בלי שגיאה.
window.wichat.hide()

מסתירה את הווידג'ט מהמסך באופן זמני בלבד. שונה מ-destroy() בכך שהיא לא מוחקת ולא הורסת שום דבר: הווידג'ט, השיחה, ההגדרות והמאזינים נשארים בדיוק כמו שהם - רק לא נראים. אם חלון הצ'אט היה פתוח הוא נסגר. קריאה חוזרת בטוחה (no-op).

// דוגמה: הסתרת הווידג'ט במסך מסוים
if (window.wichat) {
  window.wichat.hide();
}
window.wichat.show()

הפעולה ההפוכה ל-hide() - מחזירה את הווידג'ט להצגה על המסך, אותו מופע בדיוק עם אותה שיחה. אם לא נקראה קודם hide() הווידג'ט כבר מוצג, ולכן לא יקרה כלום ולא תיזרק שגיאה.

// דוגמה: הסתרה וחזרה במעבר בין מסכים
if (window.wichat) {
  window.wichat.hide();   // הווידג'ט נעלם מהמסך
  window.wichat.show();   // הווידג'ט חוזר, עם אותה שיחה
}
התנהגותפירוט
לא הורסבשונה מ-destroy(), אין ניקוי של אלמנטים, מאזינים או טיימרים - הווידג'ט ממשיך לחיות מוסתר.
שמירת שיחההיסטוריית השיחה נשמרת במלואה, וממשיכה מאותה נקודה כשקוראים ל-show().
הגדרות הצגהshow() מכבדת את הגדרות "הצג במובייל / הצג במחשב" של העסק - היא לא תציג את הווידג'ט במסך שבו הוא הושבת מהפאנל.
קריאה מיותרתshow() ללא hide() לפניה, או hide() פעמיים - לא עושות כלום ולא זורקות שגיאה.
window.wichat.updateConfig(changes)

שינויי תצורה מקומיים לדף בלבד. הפונקציה מקבלת אובייקט עם השדות שרוצים לשנות, ומחילה אותם על הווידג'ט באתר שלכם בלבד - שום דבר לא נשמר במסד הנתונים ולא משנה את ההגדרות בפאנל של wichat. כל שדה שהגדרתם כאן "דורס" מקומית את הערך המקורי מהפאנל, עד ש-resetConfig() נקרא או שהדף נטען מחדש.

שדהערכים אפשרייםמי יכול
widget_iconmessage, bot, sparkles, headphones, zap, heart, globe, phonePro / Premium / Partner בלבד
widget_position_mobilebottom-right, bottom-left, top-right, top-leftPro / Premium / Partner בלבד
widget_position_desktopbottom-right, bottom-left, top-right, top-leftPro / Premium / Partner בלבד
widget_size_mobilexsmall, small, medium, largePro / Premium / Partner בלבד
widget_size_desktopxsmall, small, medium, largePro / Premium / Partner בלבד
widget_welcomeטקסט חופשי (מחרוזת לא ריקה, עד 200 תווים) - טקסט הפתיחה שהסוכן מציג כשנפתח הצ'אטPro / Premium / Partner בלבד
widget_timergloves, robot, ribbonPro / Premium / Partner בלבד
widget_positionbottom-right, bottom-left, top-right, top-leftFree / Business בלבד (מיקום אחיד לכל המסכים)
widget_sizexsmall, small, medium, largeFree / Business בלבד (גודל אחיד לכל המסכים)

למה יש הבדל בין Free/Business ל-Pro/Premium? בתוכניות Pro/Premium לווידג'ט יש שני ערכים לכל אחד מהשדות גודל ומיקום - אחד למובייל ואחד למחשב. לכן משתמשי Pro/Premium חייבים לציין במפורש איזה מהם משנים (_mobile או _desktop) - ניסיון להשתמש בשדה הכללי (widget_position / widget_size) פשוט לא יעבוד ותופיע אזהרה ב-Console. בתוכניות Free/Business יש ערך אחד כללי לכל שדה, ולכן משתמשים בשדות הכלליים בלבד - והשדות המפוצלים (וגם widget_icon ו-widget_welcome) לא זמינים. בתוכניות Free/Business טקסט הפתיחה תמיד נשאר ברירת המחדל, והשרת שלנו הוא זה שקובע אילו שדות מותרים - כך שלא ניתן לעקוף את ההגבלה מצד הדפדפן.

דוגמאות למשתמשי Pro/Premium (כל 6 השדות):

// 1) שינוי אייקון הווידג'ט לאייקון רובוט (בדף הזה בלבד)
window.wichat.updateConfig({ widget_icon: 'bot' });

// 2) שינוי מיקום הווידג'ט במובייל לפינה השמאלית-תחתונה
window.wichat.updateConfig({ widget_position_mobile: 'bottom-left' });

// 3) שינוי מיקום הווידג'ט במחשב לפינה הימנית-עליונה
window.wichat.updateConfig({ widget_position_desktop: 'top-right' });

// 4) הקטנת הווידג'ט במובייל
window.wichat.updateConfig({ widget_size_mobile: 'small' });

// 5) הגדלת הווידג'ט במחשב
window.wichat.updateConfig({ widget_size_desktop: 'large' });

// 6) שינוי טקסט הפתיחה של הצ'אט (בדף הזה בלבד)
window.wichat.updateConfig({ widget_welcome: 'היי! מעניין אותך המוצר הזה? אני כאן לכל שאלה' });

// אפשר גם לשלב כמה שינויים בקריאה אחת:
window.wichat.updateConfig({
  widget_icon: 'headphones',
  widget_position_desktop: 'bottom-left',
  widget_size_mobile: 'xsmall'
});

אנימציית טיימר:

window.wichat.updateConfig({
  widget_timer: {
    style: 'gloves',
    text: 'המבצע מסתיים בעוד',
    ends_at: '2027-07-01T20:00:00+03:00',
    interval_seconds: 30
  }
});

// Stop the timer animation on this page only:
window.wichat.updateConfig({ widget_timer: null });

// Restore the original timer and all other panel settings:
window.wichat.resetConfig();
שדה / התנהגותפירוט
textטקסט חובה מעל השעון, עד 60 תווים. מוצג כטקסט בלבד ולא כ-HTML.
ends_atמועד סיום חובה בפורמט ISO 8601 עם אזור זמן מפורש. כל הזמנים בפאנל הם לפי Asia/Jerusalem. בקוד יש להשתמש בהיסט המתאים לתאריך בישראל: ‎+03:00 בקיץ או ‎+02:00 בחורף; אפשר גם לשלוח את אותו רגע ב-UTC עם Z. אין להשתמש בתאריך ללא אזור זמן או באזור הזמן המקומי של המבקר.
interval_secondsמספר שלם של 20 שניות לפחות, בין תחילת הופעה לתחילת ההופעה הבאה.
תצוגה וסיוםלאחר אנימציית הפתיחה, השלט נשאר 5 שניות עם שעון דיגיטלי חי HH:MM:SS, ואז חוזר לווידג׳ט. השעות הן סך השעות שנותרו ולא מתאפסות אחרי 24 שעות. כשהזמן מסתיים, גם באמצע הופעה, האנימציה מוסרת ומפסיקה ללא שגיאה.
ללא קריאות חוזרותהזמן והתדירות נקראים מההגדרות בעת הטעינה; הספירה והמחזור פועלים מקומית בדפדפן. נטען נכס אנימציה סטטי אחד, ללא בקשות חוזרות לשרת עבור הטיימר.
עדכון ואיפוסיש לשלוח את אובייקט הטיימר המלא. עדכון מחליף את המחזור הקודם ומנקה אותו; null עוצר ומסיר אותו. resetConfig משחזר את ההגדרות המקוריות ומנקה אנימציות ותזמונים קודמים, ללא שינוי במסד הנתונים. אם הטיימר המקורי הסתיים, הוא לא יוצג.
חסימותהשרת מנקה הגדרות לא תקינות או ללא מנוי מתאים ומחזיר הרשאת טיימר לפי מנוי בעל העסק. שדות לא מורשים או ערכים לא תקינים ב-updateConfig מדולגים. האנימציה מושהית בזמן צ׳אט פתוח, אנימציית פתיחה, הסתרת הווידג׳ט או לשונית לא פעילה; destroy מנקה גם אותה.

דוגמאות למשתמשי Free/Business (השדות הכלליים בלבד):

// 1) שינוי מיקום הווידג'ט (אחיד למובייל ולמחשב)
window.wichat.updateConfig({ widget_position: 'bottom-left' });

// 2) שינוי גודל הווידג'ט (אחיד למובייל ולמחשב)
window.wichat.updateConfig({ widget_size: 'large' });

// 3) שינוי אייקון - לא זמין בתוכנית Free:
window.wichat.updateConfig({ widget_icon: 'bot' });
// ← לא יקרה כלום, ותופיע אזהרה ב-Console.
התנהגותפירוט
מקומי בלבדהשינויים חיים בזיכרון הדף בלבד. רענון דף / ניווט מלא מחזירים את התצורה מהפאנל. שום דבר לא נכתב למסד הנתונים.
שדה לא מורשהשדה שלא קיים בתוכנית שלכם (או שלא נתמך בכלל) פשוט מדולג עם אזהרה ב-Console - שאר השדות באותה קריאה כן מוחלים.
ערך לא חוקיערך שאינו מהרשימה המותרת מדולג עם אזהרה ב-Console - לא נזרקת שגיאה.
אכיפת תוכניתזיהוי התוכנית מגיע מהשרת יחד עם התצורה - אי אפשר "לשחרר" שדות של Pro/Premium מה-Console בעסק בתוכניות Free / Business.
לפני טעינהקריאה לפני שהווידג'ט סיים להיטען - אזהרה ב-Console ולא קורה כלום. קראו לה אחרי שהווידג'ט נטען.
window.wichat.resetConfig()

ביטול כל השינויים המקומיים. הפונקציה מוחקת את כל השינויים שבוצעו עם updateConfig(...) ומחזירה את הווידג'ט לתצורה המקורית כפי שהיא מוגדרת בפאנל של wichat (מיקום, גודל, אייקון, טקסט פתיחה ואנימציית טיימר). האיפוס מנקה גם את מחזור הטיימר המקומי ומחזיר את הטיימר המקורי, אם הוא עדיין בתוקף. אם לא בוצעו שינויים מקומיים - הקריאה בטוחה לגמרי: לא קורה כלום ולא נזרקת שגיאה.

// דוגמה: בדף המבצעים הווידג'ט גדול ובצד שמאל,
// ובחזרה לדף הבית - חוזרים להגדרות המקוריות מהפאנל.

// בדף המבצעים:
window.wichat.updateConfig({
  widget_size_desktop: 'large',
  widget_position_desktop: 'bottom-left'
});

// בחזרה לדף הבית:
window.wichat.resetConfig();
// ← הווידג'ט חוזר בדיוק להגדרות שבפאנל של wichat

// בטוח גם בלי שינויים קודמים:
window.wichat.resetConfig(); // לא קורה כלום, אין שגיאה

חשוב: resetConfig() מבטל שינויים מקומיים בלבד. הוא לא נוגע בהגדרות בפאנל של wichat - הן מעולם לא השתנו, כי updateConfig(...) לא כותב אליהן.

התנהגויות מובנות
תכונהפירוט
עיצוב מבודדהווידג'ט מזריק אלמנטים עם inline styles ו-z-index גבוה - לא מושפע מ-CSS של האתר ולא משפיע עליו.
מובייל/דסקטופתצוגה לפי הגדרות העסק בדאשבורד (הצג במובייל / הצג במחשב), עם גודל נפרד לכל מסך בתוכניות Pro/Premium.
RTLחלון הצ'אט תמיד בעברית ו-RTL, ללא תלות בשפת האתר המארח.
עסק מושבתאם העסק הושבת בדאשבורד, השרת לא מחזיר קונפיגורציה והווידג'ט לא יוצג כלל.

19נתונים דינמיים

פיצ'ר "נתונים דינמיים" (למנויי pro, partner,Premium) מאפשר לסוכן ה-AI לשלוף מידע חי מהמערכת שלכם בזמן השיחה - מלאי, סטטוס הזמנות, זמינות תורים וכדומה - ולענות ללקוחות על בסיס נתונים עדכניים. יש שתי דרכים לחבר: חיבור ידני (אתם בונים את ה-Endpoint בעצמכם) או Vibe Coding (מעתיקים prompt מוכן לסוכן ה-AI של הפלטפורמה שבה בניתם את האתר).

הארכיטקטורה

wichat לעולם לא מקבלת גישה ישירה למסד הנתונים שלכם. אתם יוצרים Endpoint ייעודי בשרת שלכם שמאמת מפתח API, קורא ממסד הנתונים בקריאה בלבד, ומחזיר אך ורק את המידע שבחרתם לחשוף. הסוכן פונה אליו רק כששאלת הלקוח דורשת מידע עדכני:

wichat AI  ->  wichat Backend  ->  Your Endpoint  ->  Your Database

המפתח נשמר מוצפן בצד השרת של wichat ואינו נחשף לעולם לדפדפן או למשתמש הקצה. הקריאה היא תמיד קריאה בלבד (read-only) - wichat לעולם לא כותבת או מוחקת דרך ה-Endpoint.

אפשרות 1: חיבור ידני - חוזה ה-Endpoint

ה-Endpoint שלכם חייב לעמוד בחוזה הבא:

מאפייןדרישה
MethodPOST בלבד
כתובתHTTPS ציבורית בלבד. HTTP, localhost וכתובות פנימיות נדחים.
אימותכותרת Authorization: Bearer <API_KEY> - מפתח ייעודי ל-wichat שנשמר כ-secret בשרת שלכם. בקשה ללא מפתח תקין - החזירו 401.
Redirectsחסומים - ה-Endpoint חייב לענות ישירות ללא הפניה (3xx).
זמן תגובהמומלץ לענות תוך שניות בודדות - בקשה איטית מדי תיכשל.

גוף הבקשה שנשלח אליכם:

POST /api/wichat/data HTTP/1.1
Content-Type: application/json
Authorization: Bearer YOUR_WICHAT_API_KEY

{
  "query": "נשאר Nike Air Force במידה 42?",
  "read_only": true
}

גוף התשובה - JSON פשוט ועקבי עם המידע המינימלי הנחוץ בלבד:

{
  "success": true,
  "data": [
    { "product": "Nike Air Force 1", "size": "42", "in_stock": true, "quantity": 3 }
  ]
}
דרישות אבטחה מחייבות
דוגמה מלאה - Node.js + Expressserver.js
// WICHAT_API_KEY נשמר בסביבת השרת בלבד
app.post('/api/wichat/data', express.json(), async (req, res) => {
  // 1. אימות מפתח
  const auth = req.headers.authorization || '';
  if (auth !== 'Bearer ' + process.env.WICHAT_API_KEY) {
    return res.status(401).json({ success: false });
  }

  // 2. קריאת השאילתה עם הגבלת אורך
  const query = String(req.body?.query || '').slice(0, 300);

  // 3. חיפוש מוגדר מראש בלבד - לעולם לא SQL שמגיע מהלקוח
  const products = await db.products.findByName(query); // read-only

  // 4. החזרת מידע מינימלי בלבד
  res.json({
    success: true,
    data: products.map((p) => ({
      product: p.name,
      size: p.size,
      in_stock: p.quantity > 0,
      quantity: p.quantity,
    })),
  });
});

אותו עיקרון עובד בכל backend - Next.js API Route, PHP, Python/Flask, Firebase Function, Supabase Edge Function וכדומה: אימות מפתח, קריאה בלבד, החזרת מידע מינימלי.

יצירת מפתח API ייעודי
# יצירת מפתח אקראי ב-Node
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

# או ב-OpenSSL
openssl rand -hex 32

במקרה חשד לדליפה - החליפו (rotate) את המפתח בשני הצדדים מיד: בשרת שלכם ובכפתור "החלף API Key" בדאשבורד.

אפשרות 2: Vibe Coding

בניתם את האתר עם פלטפורמת Vibe Coding (Base44, Lovable, Bolt, v0 וכדומה)? העתיקו את ה-prompt הבא לסוכן ה-AI של הפלטפורמה - התאימו את סעיף 7 לסוג הנתונים שתרצו לחשוף - והוא ייצור עבורכם Endpoint ומפתח מאובטחים המוכנים לחיבור:

אני משתמש ב-wichat - פלטפורמת סוכני AI לעסקים. אני צריך שתיצור עבורי באתר Endpoint ייעודי ומאובטח ש-wichat תוכל לקרוא כדי לקבל נתונים בזמן אמת ממסד הנתונים של האתר.

מה לבנות:
1. צור endpoint חדש בצד השרת (backend) של האתר בנתיב ייעודי, למשל: POST /api/wichat/data
2. צור API Key ייעודי, חזק ואקראי עבור wichat בלבד (לא סיסמת מסד הנתונים ולא מפתח קיים שנותן גישה מלאה למערכת). שמור אותו כ-secret בצד השרת בלבד - לעולם לא בקוד ה-frontend. אם ביכולתך, צור את ה-API Key בעצמך ואז תגיד לי מה הוא כדי שאדביק אותו בממשק wichat, אם אתה לא יכול תגיד לי כיצד ליצור אותו ומה לרשום.
3. ה-endpoint יקבל בקשת POST עם JSON בפורמט: { "query": "<טקסט חופשי>", "read_only": true } ועם כותרת: Authorization: Bearer <API_KEY>
4. אמת את המפתח בכל בקשה (authentication + authorization). בקשה ללא מפתח תקין - החזר 401 בלי שום מידע נוסף.
5. ה-endpoint הוא קריאה בלבד (read-only): אסור לבצע בו שום יצירה, עדכון או מחיקה במסד הנתונים, בשום מקרה.
6. בצע validation על ה-input. אסור להעביר את query ישירות למסד הנתונים ואסור לאפשר SQL או שאילתות שרירותיות שמגיעות מהלקוח - השתמש בחיפוש/שליפה מוגדרים מראש בלבד.
7. החזר אך ורק את המידע הבא: [תאר כאן את המידע שברצונך לחשוף, למשל: שם מוצר, מידה, צבע, האם במלאי וכמות זמינה]
8. אסור להחזיר מידע אישי, פרטי לקוחות, כתובות, סיסמאות, פרטי תשלום, מפתחות, הערות פנימיות או כל credential.
9. פורמט התשובה: JSON מוגדר וברור, למשל:
{ "success": true, "data": [ { "product": "Nike Air Force 1", "size": "42", "in_stock": true, "quantity": 3 } ] }
10. אם אפשר - הוסף rate limiting בסיסי ל-endpoint.

לאחר שתסיים, תן לי את כתובת ה-Endpoint המלאה (HTTPS) ואת ה-API Key כדי שאזין אותם בממשק של wichat.
חיבור בדאשבורד

20Public API

גישת קריאה (Read-only) ב-JSON לשיחות, לפניות ולתורים של העסקים שלכם - לחיבור CRM, אוטומציות (Make / Zapier / n8n), דשבורדים ומערכות פנימיות. זמין למנויי Business, Premium ו-Partner.

אימות
Endpoints

כתובת בסיס: https://wichat.ai/functions/public-api. כל הבקשות הן GET. את business_key מעתיקים מכרטיס העסק בדאשבורד (אותו מפתח שמשמש ב-data-key של הווידג'ט).

Resourceכתובתפילטרים
שיחות?business_key=KEY&resource=conversationsstatus = open | closed
include_messages = true
פניות?business_key=KEY&resource=leadsread = true | false
include_messages = true
תורים?business_key=KEY&resource=appointmentsstatus = booked | cancelled
date_from, date_to (YYYY-MM-DD)

פרמטרים משותפים: limit (ברירת מחדל 50, מקסימום 100) ו-cursor לדפדוף. התוצאות מסודרות מהחדש לישן.

דוגמה - cURL
curl "https://wichat.ai/functions/public-api?business_key=YOUR_BUSINESS_KEY&resource=leads&read=false&limit=20" \
  -H "Authorization: Bearer wc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
דוגמה - Node.js (דפדוף על כל העמודים)
const BASE = 'https://wichat.ai/functions/public-api';
const KEY = process.env.WICHAT_API_KEY; // לעולם לא בקוד צד-לקוח

async function fetchAll(businessKey, resource, params = {}) {
  const items = [];
  let cursor = null;
  do {
    const qs = new URLSearchParams({ business_key: businessKey, resource, limit: '100', ...params });
    if (cursor) qs.set('cursor', cursor);
    const res = await fetch(`${BASE}?${qs}`, { headers: { Authorization: `Bearer ${KEY}` } });
    if (!res.ok) throw new Error((await res.json()).error.message);
    const json = await res.json();
    items.push(...json.data);
    cursor = json.pagination.next_cursor;
  } while (cursor);
  return items;
}

const appointments = await fetchAll('YOUR_BUSINESS_KEY', 'appointments', { status: 'booked', date_from: '2026-01-01' });
מבנה התשובה
{
  "business": { "key": "YOUR_BUSINESS_KEY", "name": "שם העסק" },
  "data": [
    {
      "id": "6aa46b5c23ebeb8708e76fcc",
      "visitor_id": "v_8f3a",
      "contact_name": "דנה לוי",
      "contact_phone": "050-0000000",
      "contact_email": "dana@example.com",
      "summary": "מתעניינת בחבילת פרימיום",
      "read": false,
      "created_date": "2026-09-11T20:58:04.530000",
      "updated_date": "2026-09-11T20:58:04.530000"
    }
  ],
  "pagination": { "limit": 50, "has_more": true, "next_cursor": "bzo1MA" }
}
Resourceשדות
conversationsid, visitor_id, summary, status, message_count, last_message_at, created_date, updated_date + messages[] (role, content, created_date) כאשר include_messages=true
leadsid, visitor_id, contact_name, contact_phone, contact_email, summary, read, created_date, updated_date + messages[] כאשר include_messages=true
appointmentsid, visitor_id, date, start_time, end_time, duration_minutes, service_name, service_price, staff_name, customer_name, customer_phone, customer_email, customer_details, status, cancelled_at, rescheduled_from, created_date, updated_date
שגיאות ומגבלות

כל שגיאה מוחזרת בפורמט אחיד: { "error": { "code": "...", "message": "..." } }

HTTPcodeמשמעות
400INVALID_CURSORה-cursor לא תקין - התחילו את הדפדוף מחדש.
401UNAUTHORIZEDHeader חסר או מפתח שגוי / שנמחק.
403FORBIDDENהעסק אינו בבעלות החשבון שאליו שייך המפתח.
403PLAN_REQUIREDהתוכנית של החשבון אינה כוללת שיחות / פניות / תורים.
404NOT_FOUNDbusiness_key לא קיים או resource לא מוכר.
405METHOD_NOT_ALLOWEDרק GET נתמך. ה-API הוא לקריאה בלבד.
429RATE_LIMITEDעד 60 בקשות לדקה לכל מפתח. כבדו את ה-Header Retry-After.

21פתרון תקלות

בעיהסיבות נפוצות ופתרון
הווידג'ט לא מופיע בכלל 1) data-key חסר או שגוי - בדקו את ה-Console (הודעת [wichat]). 2) העסק מושבת בדאשבורד. 3) כיביתם "הצג במובייל"/"הצג במחשב" בהגדרות הווידג'ט. 4) בטעינה דינמית - שכחתם setAttribute('data-key', ...).
הווידג'ט נעלם אחרי ניווט ב-SPA ה-Framework הסיר את תגית הסקריפט וההרס האוטומטי הופעל. אם רוצים אותו בכל הדפים - הזריקו אותו ב-HTML הראשי (index.html / layout) ולא בתוך קומפוננטת דף.
שני כפתורים מופיעים הסקריפט הוזרק פעמיים (למשל גם ב-index.html וגם ב-useEffect). השאירו נקודת הזרקה אחת בלבד, וב-React ודאו cleanup ב-useEffect (חשוב במיוחד ב-StrictMode שמריץ effects פעמיים בפיתוח).
הסקריפט נחסם (Console: CSP) אם לאתר יש Content-Security-Policy, הוסיפו: script-src https://wichat.ai וגם connect-src https://wichat.ai.
השיחה לא נשמרת בין ביקורים ההיסטוריה נשמרת ב-localStorage. במצב גלישה פרטית / WebView ללא domStorageEnabled (Android) או ללא websiteDataStore (iOS) - כל טעינה תתחיל שיחה חדשה.
ב-WebView הצ'אט לא שולח הודעות ודאו JavaScript מאופשר, שיש הרשאת אינטרנט, ושהעברתם baseUrl תקין (https://wichat.ai) בטעינת ה-HTML - בלעדיו בקשות הרשת עלולות להיחסם.
הכפתור מוסתר מאחורי אלמנט באתר הווידג'ט משתמש ב-z-index מקסימלי (2147483000). אם אלמנט באתר עדיין מכסה אותו - הנמיכו את ה-z-index של אותו אלמנט, או שנו את מיקום הווידג'ט (פינה אחרת) בהגדרות בדאשבורד.

חסרה פלטפורמה? הפתרון הכללי תמיד עובד: מצאו איפה מזריקים HTML לפני </body> בפלטפורמה שלכם, והדביקו שם את שורת הסקריפט. לשאלות נוספות - היכנסו למסך "הטמעה" בדאשבורד, שם יש גם מחולל הנחיות ל-AI (Vibe Coding) שמתאים את ההוראות לפרויקט שלכם.