דילוג לתוכן הראשי
PPC overview|Landing Pages|CTA|
Marketing data

Analytics

התג באתר, התחברות אחת, ודוחות GA4 מהטרמינל. כולל Google Ads ומדידה של דפי נחיתה.

#ga-events

כל האירועים ואיך הם נמדדים

עודכן לאחרונה: 7.11.2026

רק באתר של הסטודיו: בפרודקשן, על הדומיינים של ANALYTICS.hosts, ולא בדמואים, בדוקס וב-beta (הקליקים בודקים את הנתיב). קליק נתפס לפי ה-href של הלינק, לא לפי קלאס או קומפוננטה: כפתור שמשנה צורה ממשיך להיספר כל עוד ה-href שלו אותו href.

קליקים (listener אחד, capture)

אירועלאןמה מפעיל (סלקטור / קוד)איךהקובץ
Click to call (ראשית)Ads · Meta Contact {call}a[href^="tel:" + STUDIO.phone]קליק, selectorSiteTags.tsx · ADS_CLICKS
Whatsapp (ראשית)Ads · Meta Contact {whatsapp}a[href^=STUDIO.whatsapp]קליק, selectorSiteTags.tsx · ADS_CLICKS
Visit contact us page (משנית)Ads · Meta Contact {contact}a[href="/contact"], a[href$="#footer-lead"], a[href$="#lead"]קליק, selectorSiteTags.tsx · ADS_CLICKS
המרה של אלמנט אחדAds[data-ads="AW-…/…"]קליק, אטריביוטSiteTags.tsx

המשפך: cta_click (target) ← generate_lead (form_name). וואטסאפ וטלפון לבד (contact): הקליק הוא הליד. ליד מהטופס בתחתית בלי קליק לפניו: מישהו שגלל ומילא לבד. עד 7.11 היו כאן lead_intent, lp_intent ו-sticky_banner_click / close; ההיסטוריה שלהם נשארת ב-GA4 בשמות הישנים.

אירועים ב-GA4

אירועלאןמה מפעיל (סלקטור / קוד)איךהקובץ
cta_click {location, target}GA4קליק על a[href="/contact"] (target: popup) או a[href$="#lead"], a[href$="#footer-lead"] (target: footer-form). location: ה-data-cta של הכפתור, אחרת navbar / footer / pageקליק, לפי hrefSiteTags.tsx
contact {method, location}GA4 (וב-Meta: Contact)קליק על tel: (method: call) או wa.me / whatsapp (method: whatsapp). השם של Meta לזהקליק, לפי hrefSiteTags.tsx
generate_lead {form_name}GA4 · Ads (ANALYTICS.adsConversion) · Meta LeadtrackLead(leadName) אחרי שהשרת אישר. form_name: contact, contact-popup, footer, landingקוד, אחרי שליחהlib/analytics.ts · LeadForm
cta_dismiss {location}GA4סגירת הפס הצף בדפי השירות (location: sticky_banner). מול cta_click באותו location: מפריע או עוזרקוד, onCloseServiceLead.tsx
search_selectGA4בחירת תוצאה בחיפוש של הדוקסקודapp/docs/algolia/AlgoliaSearchBox.tsx

צפיות בדף

אירועלאןמה מפעיל (סלקטור / קוד)איךהקובץ
page_viewGA4טעינה, ו-GA4 לבד במעבר דף של Nextאוטומטי (gtag config)SiteTags.tsx
PageViewMetaטעינה, וכל pushState / popstate (מעבר דף של Next)קוד, עוטף את history.pushStateSiteTags.tsx · metaPixel

#ga-tag

התג באתר

המזהים של התגים (GA4_ID, ADS_ID) הם const בראשcomponents/studio/SiteTags.tsx; propertyId ו-hosts ב-ANALYTICS ב-lib/site.ts. לקוח חדש = להחליף את כל ה-const בראש SiteTags.tsx, כולל ADS_CLICKS (ההמרות על קליק), ואת כל השדות ב-ANALYTICS, כולל adsConversion ו-searchConsoleSite. אחרת האתר של הלקוח שולח המרות לחשבון ה-Ads של הסטודיו. הקובץ טוען את gtag רק ב-production, רק אחרי שהעמוד נטען, כי הסקריפט שוקל 176KB, ורק כשהכתובת ב-hosts. מעברי עמוד בצד הלקוח נספרים לבד, דרך ה-enhanced measurement של GA.

התג של Google Ads (ADS_ID, ה-AW- של החשבון) נטען על אותו gtag. הוא מודד בלבד כל עוד ADS_REMARKETING כבוי; להדליק אותו = גם לעדכן את הפסקה על פרסום ב-/privacy.

SiteTags.tsx הוא ה-Tag Manager של האתר, בקוד: כל סקריפט חיצוני גר שם ורק שם, מאחורי אותה בדיקה (production, hosts, ?notrack). תג חדש (Hotjar, Clarity, פיקסל) = const של המזהה בראש הקובץ + פונקציה אחת. לקוח שעובד עם Tag Manager אמיתי: הקובץ מוחלף בסניפט של GTM, ושאר הקוד לא משתנה.

לא לספור את עצמנו

קוד שלנו, לא תכונה של GA4

פותחים פעם אחת את הקישור בכל דפדפן שלנו, כולל בנייד ובדפדפן שנפתח מתוך וואטסאפ. הוא שומר סימון בדפדפן, ו-components/studio/SiteTags.tsx לא טוען בו את GA יותר. זה מחליף סינון IP בנייד, כי בסלולר אין IP קבוע. מחיקת נתוני גלישה מוחקת גם את הסימון.

?track מבטל את הסימון. בדיקה: לגלוש קצת, ואז npm run ga -- realtime, והדפדפן המסומן לא מופיע.

// components/studio/SiteTags.tsx
const GA4_ID = 'G-XXXXXXXXXX'      // Admin > Data streams > the web stream
const ADS_ID = 'AW-XXXXXXXXXX'     // Google Ads tag ('' = off)

// lib/site.ts
export const ANALYTICS = {
  propertyId: '123456789',         // Admin > Property settings, or: npm run ga -- accounts
  hosts:      ['www.client.co.il', 'client.co.il'],  // the tags load nowhere else
} as const;

#ga-setup

הגישה (פעם אחת)

משתמש רובוט אחד (service account) קורא גם את GA וגם את Ads. הוא נוצר ב-Google Cloud, והמייל שלו מתווסף בממשק של GA (Viewer) ושל Ads (Standard) כמו כל משתמש. אין קישור התחברות, אין passkey, ואין תוקף. המפתח שלו יושב ב-~/.google-marketing/service-account.json, מחוץ לריפו. לקוח חדש מוסיף את אותו מייל לחשבונות שלו, וה-propertyId נכנס ל-lib/site.ts בריפו שלו. בלי פרויקט חדש.

המדריך, צעד צעד עם צילומי מסך
  • בתפריט ☰, הכוכב ☆ ליד Google Auth Platform וליד APIs & Services מצמיד אותם למעלה. אחרת הם קבורים ב-View all products.
  • ברשימת Enabled APIs יש כ-20 API שגוגל מפעיל לבד בכל פרויקט (BigQuery, Storage, Logging). לא צריך אותם ולא מזיקים: בלי Billing הם לא יכולים לעלות כסף. Filter: Analytics מראה את שני שלנו.

באנליטיקס

  1. 01
    ניהולניהול הגישה לנכס+המייל של הרובוטViewer

    המייל נגמר ב-iam.gserviceaccount.com. עד שהוא נוסף, ga.mjs נופל להתחברות הישנה.

  2. 02
    ניהולקישורים למוצריםGoogle Ads linksקישור

    בלעדיו אין שם קמפיין, עלות או קליקים. הנתונים נכנסים מיום הקישור והלאה.

  3. 03
    ניהולאירועים

    לסמן כ-key event את מה שנחשב ליד: קליק לוואטסאפ, שליחת טופס.

  4. 04
    ניהולמקורות נתוניםהזרםקביעת ההגדרות של התגהצגת הכולהגדרת תנועת גולשים פנימיתCreate

    בתנאי: IP address equals, והערך הוא ה-IP שלך. הקישור באותו מסך מראה אותו.

החלופה הישנה, OAuth: npm run google:auth -- --account <email> פותח את מסך ההסכמה של גוגל. הסקריפטים משתמשים בה רק איפה שהרובוט עוד לא נוסף. האפליקציה ב-Testing, אז התוקף 7 ימים.

#ga-reports

הדוחות

scripts/google/ga.mjs. ברירות מחדל: 28 ימים, 20 שורות. הדגלים, לכל דוח:

--days N        the range, default 28
--limit N       rows, default 20
--path /x       pages / landing: only paths that begin with /x
--property <id> another property (a client); default: lib/site.ts
--json          the raw API response
npm run ga -- accounts

כל הנכסים שהחשבון רואה, עם ה-ID. כך מוצאים את ה-propertyId של לקוח.

npm run ga -- overview --days 7

משתמשים, סשנים, מעורבות, key events: לפי יום ושורת סיכום.

npm run ga -- pages

העמודים הנצפים ביותר, עם משתמשים וזמן מעורבות.

npm run ga -- landing --path /landing_pages/

דפי נחיתה: סשנים, מעורבות ו-key events לכל דף כניסה.

npm run ga -- sources

מקור / מדיום: גוגל אורגני, ישיר, פייסבוק, cpc.

npm run ga -- campaigns

קמפיינים לפי utm_campaign, עם המקור.

npm run ga -- ads

קמפיינים של Google Ads: חשיפות, קליקים, עלות, key events. רק אחרי קישור Ads ל-GA.

npm run ga -- events

כל האירועים וכמה פעמים קרו. כאן רואים אם generate_lead (טופס) ו-click (וואטסאפ) נמדדים.

npm run ga -- devices

מובייל / דסקטופ / טאבלט.

npm run ga -- realtime

מי באתר ב-30 הדקות האחרונות. בדיקה מהירה שהתג עובד או שהסינון הפנימי תופס.

npm run ga -- raw '{…}'

כל גוף של runReport כמו שהוא, לשאלה שאין לה דוח מוכן.

#ga-ads

Google Ads

שתי דרכים, ושתיהן מחוברות. Ads מקושר ל-GA (צעד 02 באנליטיקס), אז עלות וקליקים לפי קמפיין נכנסים ל-GA. וה-API של Ads ישירות, דרך הרובוט: הטקסטים של המודעות, ההמרות, מונחי החיפוש. התקנה במדריך, ושם גם מה לא צריך (MCC, developer token).

npm run ga  -- ads --days 30     # through GA: campaign, cost, clicks, leads
npm run ads -- campaigns         # status, budget, impressions, clicks, cost
npm run ads -- ads               # every headline and description, with approval
npm run ads -- conversions       # conversion actions: primary or not
npm run ads -- search-terms      # what people typed (Search campaigns)
npm run ads -- raw "<GAQL>"      # any Google Ads query
npm run ads -- keyword "…" --group "…"   # a keyword on an ad group (--negative for a negative)
npm run ads -- adgroup "…"               # a new ad group in the Search campaign
npm run ads -- ad --group "…" --url … --h … --d …   # a responsive search ad
npm run gsc -- queries           # Search Console: organic searches, position
npm run gsc -- pages --page /landing_pages  # the same per page
npm run gsc -- sitemaps          # the sitemap: submitted, read, indexed
npm run gsc -- sitemap-submit    # (re)submit /sitemap.xml
npm run gsc -- inspect --sitemap /guides  # in Google's index or not, and why, per page
npm run rank                    # Google Israel position for rank/keywords.txt (Serper), shown at /beta/rank

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

#ga-form

הטופס באתר

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

שלושה טפסים שולחים לאותו מקום: עמוד צור קשר, הטופס בפוטר והטופס בעמודי השירותים. הם שולחים ל-app/api/contact/route.ts, שם הקוד שולח מייל דרך Resend. אחרי שליחה מוצלחת כל טופס קורא ל-trackLead()מ-lib/analytics.ts, וזה האירוע generate_lead ב-GA. עם ANALYTICS.adsConversion הוא יורה גם את ההמרה של Ads.

המרות על לחיצה (טלפון tel:, וואטסאפ wa.me, "דברו איתנו") הן הטבלהADS_CLICKS בראש SiteTags.tsx: שורה = selector של לינק + ה-send_to מהקוד של ההמרה ב-Ads. listener אחד על הדף, אז כל לינק שתואם נספר, גם כזה שיתווסף מחר. נספרת הלחיצה, לא שיחה או הודעה שנשלחה.

הבאנר הצף בעמודי השירותים: הלחיצה עליו היא cta_click {location: sticky_banner} (לפי ה-href, ב-SiteTags), והסגירה ב-X היא cta_dismiss מאותו location. אם יש יותר סגירות מלחיצות, הוא בעיקר מציק. שם אחד עם פרמטר (7.11): צריך לרשום פעם אחת את location, target ו-method כ-custom dimensions ב-GA4, ואז כל מיקום חדש נראה בדוחות לבד.

const ADS_CLICKS = [
  { selector: 'a[href^="tel:"]',   sendTo: 'AW-…/…' },   // phone, primary
  { selector: 'a[href*="wa.me/"]', sendTo: 'AW-…/…' },   // WhatsApp, primary
  { selector: 'a[href="/contact"],…', sendTo: 'AW-…/…' }, // "דברו איתנו", secondary
]

המייל: Resend

RESEND_API_KEY חובה, ב-.env.local וגם ב-Vercel (Settings, Environment Variables). בלעדיו הטופס באתר החי מחזיר שגיאה. CONTACT_TO_EMAIL ו-CONTACT_FROM_EMAIL אופציונליים: בלעדיהם הנמען הוא STUDIO.email מ-lib/site.ts. בלי דומיין מאומת ב-Resend המייל יוצא מ-onboarding@resend.dev ומגיע רק לבעל החשבון, וזה מספיק להתראה ללקוח.

ההמרה: generate_lead

ה-enhanced measurement של GA לא קולט את הטפסים שלנו, כי הם שולחים בלי לטעון עמוד (בדוח events יש form_start ואין form_submit). לכן האירוע נשלח מהקוד, ורק אחרי שהמייל באמת יצא. הפרמטר form_name אומר מאיזה טופס: contact, footer או service.

לסמן כהמרה

האירוע מופיע ב-GA רק אחרי שליחה אמיתית באתר החי, עד 24 שעות. אז: צעד 03 באנליטיקס (למעלה), כוכב ליד generate_lead. ב-Google Ads ההמרה של הטופס נשלחת ישירות מהקוד (adsConversion ב-lib/site.ts). ייבוא של generate_lead מ-Google Analytics 4 רק כש-adsConversion ריק, ואף פעם לא שתיהן כ-primary: אחרת כל פנייה נספרת פעמיים.

לקוח חדש

הטפסים וה-route מגיעים עם התבנית, והקריאה ל-trackLead כבר בתוכם. מגדירים את משתני הסביבה של Resend ואת ANALYTICS ב-lib/site.ts. טופס חדש שנבנה לדף נחיתה קורא ל-trackLead עם שם משלו, למשל trackLead('lp-dentist').

בדיקה: שולחים טופס באתר החי, ואז npm run ga -- realtime או npm run ga -- events --days 1. בדפדפן עם ?notrack האירוע לא יישלח, וזה מכוון.

#ga-landing

דפי נחיתה

דף נחיתה נמדד בשלושה דברים. הקוד כבר בתבנית, השאר הגדרות ב-GA וב-Ads:

מאיפה הגיעו

Google Ads מקושר מסמן לבד (gclid). כל מקור אחר מקבל UTM בקישור, למשל ?utm_source=facebook&utm_medium=paid&utm_campaign=lp-dentist. שם הקמפיין באותיות קטנות ובמקפים, אחרת GA סופר כמה גרסאות שלו כקמפיינים שונים.

מה עשו

קליק יוצא, כולל וואטסאפ וטלפון, נמדד לבד כ-click. שליחת טופס נמדדת כ-generate_lead מהקוד שלנו (הטופס, למעלה). את שניהם מסמנים כ-key event, ורק אז הם נספרים כהמרה ו-Ads יכול לייבא אותם.

איך הדף עובד

npm run ga -- landing --path /landing_pages/: סשנים, מעורבות ו-key events לכל דף, ו-campaigns לאותו דבר לפי קמפיין.

הדף עצמו

דף נחיתה של לקוח יושב על הדומיין של הלקוח, אז הוא בתוך ה-hosts שלו ונספר. דף נחיתה על preview לא נספר, וזה מכוון: בודקים עליו, לא מפרסמים אותו.

#ga-traps

מלכודות

CLOUD_PROJECT_NOT_APPROVED_FOR_PRODUCTION

הרובוט נכנס, אבל הפרויקט ב-Cloud ברמת Test: רק חשבונות בדיקה. Google Ads API > Access levels > Manage > Apply for access (Explorer). מאושר תוך דקות.

NOT_ADS_USER

המייל של הרובוט עוד לא משתמש בחשבון ה-Ads. Admin > Access and security > + . בלי אישור, תופס מיד.

SERVICE_DISABLED

אחד משני ה-API לא מופעל בפרויקט. השגיאה כוללת את שם ה-API ואת הקישור להפעלה. Admin עובד ו-Data לא (או הפוך) זה המצב הנפוץ.

הכניסות שלנו נספרות

התג נטען רק על ANALYTICS.hosts, אז גרסאות preview לא נספרות. הגלישה שלנו באתר האמיתי כן, עד שמגדירים IP (צעד 04 באנליטיקס) ופותחים ?notrack בנייד. בדוח sources זה נראה ככה: google / organic.

החשבון רואה גם לקוחות

בהתחברות הישנה accounts מחזיר כל נכס שהמשתמש רואה, כולל לקוחות. הרובוט רואה רק נכסים שהוסיפו אותו אליהם. ברירת המחדל היא propertyId מ-lib/site.ts; לקוח אחר רק עם --property מפורש.

"Add domain for cross-domain measurement"

גוגל ראה את התג על דומיין אחר, כמעט תמיד preview או כתובת vercel.app ישנה. Dismiss, לא Add. מדידה בין דומיינים היא לשני דומיינים אמיתיים של אותו עסק.