Skip to content

SAMWALTON01/SAMWALTON01.github.io

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

51 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

מערכת קמפייני סמס + פאנל ווב — מסמך מסירה למפתח

גרסה: יולי 2026 • סטטוס: עובד, נבדק end-to-end, מוכן ל-production

מסמך זה מלווה את מסירת המערכת. הוא מכסה: מה נבנה, איפה כל דבר גר, איך משנים דברים נפוצים, ואיך מעבירים בעלות.

1. מה המערכת עושה

שולחים קמפיין סמס (Inforu) עם קישור אישי קצר (אסימון) לכל נמען → הנמען נכנס לפאנל ווב בסגנון וואטסאפ (תפריט פתיחה: הלוואה / משיכה מקרן הפנסיה, עם החזר מס כהצעת המשך; עברית RTL, בסגנון הבוט של אוראל) → הליד נשמר ב-DB עם סיכום אוטומטי → דשבורד ניהול (שליחה במנות, סטטיסטיקות, לידים, ייצוא).

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

קישור אישי קצר (אסימון): כל נמען מקבל קישור בצורת https://lc76nj.short.gy/zk?t=<token> (אסימון בן 10 תווים), שמפנה לפאנל בכתובת https://nahmanbot.com/?t=<token>. הטלפון והשם נשמרים ב-DB מאחורי האסימון (sms_short_links) — כך הכתובת קצרה, הטלפון לא נחשף ב-URL, וכל טעינה נרשמת כקליק. הסרה מרשימת התפוצה: במסך הראשון קיימת אפשרות "הסרה מרשימת התפוצה" שנשמרת ב-DB (sms_opt_outs) וחוסמת שליחות עתידיות — מוסרים מסוננים אוטומטית לפני כל שליחה.

גם מי שלחץ ולא סיים — נרשם עם הטלפון שלו ("ליד חם").

שמירת התקדמות: מי שנכנס לפאנל ועושה רענון / סוגר וחוזר (עד 24 שעות) — ממשיך בדיוק מאיפה שעצר, עם כל היסטוריית הצ'אט (נשמר ב-localStorage). בנוסף כל תשובה נשמרת ב-DB כליד חלקי (is_completed=false, upsert אחד ל-24 שעות — לא נוצרות שורות כפולות), וברגע הסיום אותה שורה הופכת ל-is_completed=true. בדשבורד רואים תגית "חלקי" ליד לידים כאלה.

2. ארכיטקטורה

┌─────────────────┐   לינק אישי    ┌──────────────────────────┐
│  Inforu (סמס)   │ ─────────────► │  nahmanbot.com (nginx    │
└─────────────────┘  ?p=&n=&c=     │  בשרת; GitHub Pages =    │
                                   │  גיבוי) פאנל + דשבורד    │
                                   └─────────┬────────────────┘
                                             │ RPC בלבד (anon key)
                                             ▼
              ┌───────────────────────────────────────────────────────┐
              │  DB מרכזי: Supabase self-hosted על שרת הלקוח          │
              │  db.nahmanbot.com (Kong → Postgres, 13K+ לידים)       │
              │  הפאנל כותב לידים ישירות לטבלת leads המרכזית          │
              └───────────────────────────────────────────────────────┘
                                             ▲
              ┌──────────────────────────────┴───────────────────────┐
              │  Edge Functions (בשרת + בענן כגיבוי, אותו קוד):      │
              │   send-sms-campaign ──► Inforu API                   │
              │   admin-api ◄── דשבורד (x-admin-token)               │
              │  שתיהן מדברות אל ה-DB המרכזי ב-service key שלו       │
              └──────────────────────────────────────────────────────┘

ה-DB המרכזי הוא אותו DB שהבוט וה-CRM של הלקוח עובדים איתו — ליד מהפאנל נולד ישירות בטבלת leads שהם רואים. פונקציות ה-edge מותקנות בשני מקומות במקביל (אותו קוד, אותם קבועים): ב-edge-runtime של השרת (/root/supabase/volumes/functions/, הותקן ואומת 19.7) ובפרויקט הענן הישן כגיבוי. אין בהן דאטה — רק קוד.

3. רכיבי המערכת

נתיב מה זה
index.html הפאנל ללקוחות. הפלואו (תפריט: מסלול הלוואה / מסלול החזר מס) מוטמע בקוד באובייקט FLOW
admin.html דשבורד ניהול: שליחת קמפיין / סטטיסטיקות / לידים + ייצוא CSV / קבוצות אנשי קשר
supabase/functions/send-sms-campaign/ שליחה דרך Inforu (שרת-צד, מוגן טוקן). SHORTEN_URL=false — מקצר הקישורים כבוי (גרם לבליעת הודעות, ראה §5)
supabase/functions/admin-api/ API קריאה/כתיבה לדשבורד (קמפיינים/לידים/ייצוא/קבוצות)
supabase/functions/inforu-probe/ כלי בדיקה: קישוריות + Sender IDs מורשים
supabase/migrations/ כל ה-DDL: RPCs (submit_web_lead, log_web_click, calc_summary_web) + טריגרים + טבלת קבוצות + 007: אסימונים, הסרות ומנות שליחה
supabase/migrations/007_short_links_opt_outs.sql טבלאות sms_short_links / sms_opt_outs / sms_campaign_batches, ה-view sms_campaign_stats, וה-RPCs לשליחה במנות (register_sms_campaign, claim_sms_campaign_batch, prepare_sms_batch, finish_sms_campaign_batch), לפתרון אסימון (resolve_sms_short_link), ולהסרה (opt_out_sms, opt_out_sms_by_phone)
tools/send.js סקריפט CLI חלופי לשליחה (לא דרך הדשבורד)

4. גישות וסודות

מה ערך היכן מוגדר
DB מרכזי (self-hosted) https://db.nahmanbot.com בכל הרכיבים
anon key של ה-DB המרכזי בראש index.html (SUPABASE_ANON) — מקור: /root/supabase/.env בשרת index.html
service key של ה-DB המרכזי SUPA_KEY בשתי הפונקציות — מקור: /root/supabase/.env בשרת send-sms-campaign, admin-api
Supabase Cloud (מראה מיותרת של הפונקציות — לגיבוי בלבד) dgmygsvwemgtnvmdnwnz
סיסמת דשבורד / admin token nahman-campaign-2026-x7q ADMIN_TOKEN בכל 3 הפונקציות
Inforu user: Shimon123 / token: בקוד הפונקציה send-sms-campaign/index.ts
Sender ID nahman (אומת מול ה-API) פרמטר sender / DEFAULT_SENDER

⚠️ לפני production — מומלץ לשנות את ADMIN_TOKEN (בכל הפונקציות) ולסובב את מפתח ה-service של Supabase (הוא נחשף בריפו הישן WhatsAppCrmClean/rebuild-flow.js). סיבוב: Supabase Dashboard → Settings → API → Reset service key.

5. שינויים נפוצים

נוסח הודעת ברירת מחדל: DEFAULT_MESSAGE ב-send-sms-campaign/index.ts (בדשבורד עצמו עורכים חופשי לכל קמפיין).

שאלות הפאנל: עורכים את FLOW ב-index.html. שדות נשמרים בפי field — השמות חייבים להתאים לעמודות בטבלת leads (רשימה מלאה ב-submit_web_lead). מאז 20.7 יש תפריט פתיחה: "במה נוכל לעזור לך היום?" — הלוואה / החזר מס (שני המסלולים משוכפלים מ-bot_steps של הבוט הראשי). מסלול הלוואה: סוג עובד → סכום → שם → אזור → נכס → רכב → חיובים חוזרים → עיקול → סוג כרטיס → ובסוף הצעת החזר מס (כמו בבוט). מסלול המס: הצעה → וותק → החזר קודם → הכנסה → ביטוחים → שם → אזור. lid_type נקבע מהבחירה בתפריט. מפתח ה-localStorage: nahman_funnel_v3.

כתובת הפאנל בלינקים: FUNNEL_URL ב-send-sms-campaign/index.ts היא https://nahmanbot.com/ (הפאנל מוגש מהשרת עצמו; ראה §6). הלינק שמופיע ב-SMS מוגדר ב-SHORT_BASE: https://lc76nj.short.gy/zk?t=<token> — קישור קצר דרך Short.io שמפנה לפאנל. הכתובת הישנה ב-GitHub Pages עדיין עובדת כגיבוי.

שם שולח: שדה בדשבורד / DEFAULT_SENDER בפונקציה.

קבוצות אנשי קשר: טבלת contacts (מיגרציה 003_contacts_groups.sql), RLS נעול — הגישה רק דרך admin-api (save_contacts / groups / group_contacts / delete_group / delete_contact). ייחודיות על (phone, group_name) — שמירה חוזרת לאותה קבוצה מעדכנת ולא מכפילה. בדשבורד: טאב 📇 לניהול, ובטאב השליחה — "טען מקבוצה שמורה" שממלא את רשימת הנמענים.

קיצור לינקים (כבוי 19.7!): SHORTEN_URL=false ב-send-sms-campaign/index.ts. בדיקת A/B הוכיחה שהודעות עם ShortenUrlEnable=true לא נמסרות כלל (נבלעות בשתיקה אצל Inforu — הפיצ'ר כנראה לא מופעל בחשבון), בעוד הודעות רגילות מגיעות. להפעיל מחדש רק אחרי אישור תמיכת Inforu שהמקצר פעיל בחשבון. שם שולח: הלקוח משתמש ב-sender ID מספרי (מספר טלפון) — מזינים אותו בשדה "שם שולח" בדשבורד לכל קמפיין; ברירת המחדל בקוד: DEFAULT_SENDER.

מעבר ל-DB מרכזי (בוצע 19.7): מיגרציה 004_central_integration.sql הורצה על ה-Postgres בשרת (גיבוי סכמה: /root/backups/pre-integration-2026-07-19.sql). היא מוסיפה: sms_clicks, sms_campaigns, contacts + ויו contact_group_counts

  • ה-RPCs (log_web_click, submit_web_lead, calc_summary_web) + 2 טריגרים. הכל אדיטיבי — לא נגענו בטבלאות/דאטה/קוד של הבוט.

תסריט החזר מס (בוצע 19.7): מיגרציה 005_tax_funnel.sqlhas_insurance נוסף למיפוי ב-submit_web_lead, ותוקן ב-calc_summary_web סיווג שגוי: "לא ביצעתי החזר מס" (ליד מצוין!) לא נרשם יותר כ"לא מעוניין". התיקון משפיע לטובה גם על סיכומי הבוט.

התנהגות צ'אט חופשי (בוצע 20.7): שדה טקסט חופשי זמין תמיד לצד הכפתורים — הודעה שרירותית שולחת מחדש את אותה השאלה עם האפשרויות (לא מקדמת); רק בחירת אפשרות מקדמת. לאחר סיום התהליך, כל הודעה חדשה מאתחלת מהשאלה הראשונה. כל הודעות הליד נצברות בעמודת remarks עם חותמת זמן [HH:MM:SS ,D.M.YYYY] (הראשונה עם "הודעת פתיחה:") — מיגרציה 006_remarks_log.sql.

⚠️ תיקון שורש (בוצע 20.7): קמפיינים camp12/camp07 יצאו עם לינק github.io כי הדשבורד (admin.html) קרא לפונקציות בכתובת הענן הישנה ישירות (dgmygsvwemgtnvmdnwnz.supabase.co) — שם רצה עותק מיושן של הקוד. תוקן: הדשבורד מפנה כעת ל-db.nahmanbot.com (edge-runtime של השרת, קוד מעודכן), בשרת וב-GitHub Pages. הסרת ה-Custom Domain מהענן עדיין מומלצת כניקיון, אך אינה קריטית — שום רכיב שלנו לא קורא לענן יותר.

אסימונים, הסרות ושליחה במנות (מיגרציה 007): לקמפיינים גדולים (10K+) הדשבורד מפצל את הנמענים למנות של 500 עם מזהה קמפיין אחיד (clientCampaignId) ושולח מנה-מנה דרך send-sms-campaign. לכל מנה הפונקציה: (1) register_sms_campaign (רישום/איתור ריצת הקמפיין, אידמפוטנטי), (2) claim_sms_campaign_batch (תפיסת המנה פעם אחת — מנה שכבר נשלחה חוזרת כ-already_sent ולא נשלחת שוב), (3) prepare_sms_batch (יצירת אסימונים + סינון מוסרים + דה-דופ בתוך ה-DB), (4) שליחה ל-Inforu עם קישור אסימון אישי, (5) finish_sms_campaign_batch (רישום תוצאה + עדכון מוני הקמפיין). אם הדשבורד נסגר באמצע — לחיצה חוזרת על "שיגור" ממשיכה מהמנה הבאה (מצב נשמר ב-localStorage תחת nahman_campaign_run_v2); מנה שנדחתה ניתנת לניסיון חוזר עד 3 פעמים. סטטוסי קמפיין: preparing / sending / sent / partial / attention (מנה במצב לא ודאי — דורש בדיקה ידנית). ה-view sms_campaign_stats מחשב קליקים/לידים ב-DB (מונע חיתוך שקט של PostgREST מעל 1,000 שורות). ההודעה חייבת לכלול [#Representative#] — שם מוזרק הקישור האישי.

6. פריסה (Deployment)

  • הפאנל על הדומיין הרשמי (19.7): https://nahmanbot.com מוגש מהשרת — קבצים ב-/var/www/funnel/, בלוק nginx ב-/etc/nginx/sites-available/funnel (server_name: nahmanbot.com + start.nahmanbot.com מוכן מראש), תעודת Let's Encrypt דרך certbot (חידוש אוטומטי). לעדכון: מעתיקים index.html/admin.html חדשים ל-/var/www/funnel/ — בלי restart.
  • דפים סטטיים (גיבוי): כל push ל-main → GitHub Pages מתעדכן אוטומטית (~דקה).
  • Edge Functions בשרת: מעתיקים את index.ts ל-/root/supabase/volumes/functions/<name>/ ו-docker restart supabase-edge-functions.
  • Edge Functions בענן — גיבוי (אחרי npm i -g supabase + supabase login):
    supabase functions deploy send-sms-campaign --project-ref dgmygsvwemgtnvmdnwnz
    supabase functions deploy admin-api        --project-ref dgmygsvwemgtnvmdnwnz
  • מיגרציות DB: להריץ את הקבצים ב-supabase/migrations/ לפי הסדר (SQL Editor בדשבורד Supabase או supabase db push).

7. הוספת התראות מייל על ליד חדש (בקשת הלקוח)

הנקודה המוכנה: טבלת leads, שורות חדשות עם source = 'web_funnel'. שתי דרכים מומלצות:

  1. Supabase Database Webhook על INSERT ל-leads → Edge Function חדשה ששולחת מייל (Resend/SendGrid).
  2. קריאה מתוזמנת (pg_cron / GitHub Actions) ללידים אחרונים → מייל תקופתי.

8. העברת בעלות (חשוב!)

היום הכל יושב תחת חשבונות של המפתח הקודם/הנוכחי. להעברה נקייה:

  1. GitHub: Repository → Settings → Transfer ownership → לחשבון הלקוח (או Fork לחשבון שלו + עדכון FUNNEL_URL אם שם המשתמש משתנה — ה-URL של Pages תלוי בו!).
  2. Supabase: Organization → Invite (כ-owner) → הלקוח מסיר את המפתח.
  3. Inforu: החשבון כבר של הלקוח.
  4. אחרי ההעברה: לסובב סודות (סעיף 4) ולעדכן טוקנים.

9. נתוני בדיקה

כל נתוני הבדיקה נוקו. אם יצטברו שוב:

delete from sms_clicks where campaign_name like '%test%' or campaign_name like '%בדיקה%';
delete from leads where source = 'web_funnel' and phone in ('0501234567');

10. בדיקות שבוצעו לפני המסירה ✅

  • שליחת 2 סמסים אמיתיים דרך Inforu — התקבלו, Sender nahman תקין
  • לחיצה → רישום מייד (טלפון+קמפיין+user-agent) כולל זיהוי בוטים (Google-Read-Aloud)
  • מילוי מלא של 12 השאלות → ליד עם כל השדות, summary אוטומטי, hechzer_mas, דה-דופ 24 שעות
  • דשבורד: התחברות, סטטיסטיקות, לידים, ייצוא
  • קבוצות: שמירה (כולל דה-דופ ונרמול טלפונים), עדכון קבוצה קיימת, צפייה, מחיקת קבוצה/איש קשר, טעינה לטאב שליחה
  • רענון באמצע הפאנל: היסטוריה מלאה + המשך מאותה שאלה; ליד חלקי ב-DB תוך שניות; השלמה אחרי רענון מעדכנת את אותה שורה (is_completed=true, summary + hechzer_mas תקינים, בלי כפילויות); רענון אחרי סיום מציג את הצ'אט המושלם
  • הרשאות: ה-anon key לא יכול לקרוא/לכתוב אף טבלה — רק 2 ה-RPCs המסוננים
  • אינטגרציית DB מרכזי: לחיצה + ליד חלקי מהפאנל נרשמו ישירות ב-Postgres בשרת (אומת ב-psql), CORS דרך Kong תקין, מיגרציית 004 הורצה בטרנזקציה אחת עם COMMIT נקי
  • פונקציות מקומיות בשרת (19.7): admin-api עונה groups תקין + 401 על טוקן שגוי, send-sms-campaign OPTIONS 204 — אומת ששרת ה-edge-runtime המקומי בלוגים; שום רכיב במערכת הראשית (בוט/דשבורד) לא מפנה לפרויקט הענן הישן (אומת ב-grep מלא)
  • פאנל על דומיין רשמי (19.7): https://nahmanbot.com + /admin.html עונים 200 עם תעודה תקינה והפניית http→https; FUNNEL_URL עודכן והופעל בשרת; crm/db/waha לא הושפעו
  • תסריט החזר מס (19.7): מיגרציית 005 COMMIT נקי; RPC עם כל שדות המס — ליד מלא "החזר מס סיים תהליך" + hechzer_mas=true + has_insurance נשמר; ליד דחייה "החזר מס לא מעוניין"; התיקון מונע סיווג שגוי של "לא ביצעתי החזר מס"; הפאנל החי מציג את התסריט החדש (אומת בכותרת וב-FLOW); דאטה בדיקה נוקה
  • התנהגות צ'אט חופשי (20.7, e2e בדפדפן): הודעה חופשית בשאלת רשימה → אותה שאלה נשלחת מחדש עם האפשרויות (ללא התקדמות); אחרי סיום התהליך → הודעה חדשה מאתחלת מהשאלה הראשונה; שתי ההודעות נצברו ב-remarks בפורמט [HH:MM:SS ,D.M.YYYY] (ראשונה עם "הודעת פתיחה:") — אומת ב-DB; מיגרציית 006 הורצה ואומתה ב-RPC; דאטת בדיקה נוקתה
  • תפריט הלוואה/החזר מס (20.7, e2e בדפדפן על Pages): תפריט פתיחה עם שתי בחירות; מסלול הלוואה המלא (11 מסכים) הושלם עד תודה כולל הצעת המס המשולבת — ליד נשמר עם lid_type='הלוואה', כל השדות, summary="סיים תהליך הלוואה לכל מטרה + החזר מס בתהליך", hechzer_mas=true; אומת גם ב-RPC ישיר; דאטת בדיקה נוקתה

About

NahmanBot web funnel — static lead-qualification funnel (SMS campaigns)

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages