mktgtech commited on
Commit
5fcd213
ยท
verified ยท
1 Parent(s): 6244a15

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +30 -17
app.py CHANGED
@@ -156,6 +156,10 @@ def enrich_leads_with_visits(df, start_date, end_date, max_rows=None, progress=g
156
  print(f"๐Ÿ•ต๏ธ Deep enriching {total} rows ({start_date} to {end_date})...")
157
 
158
  for index, row in target_df.iterrows():
 
 
 
 
159
  lead_id = row["lead_id"]
160
  try:
161
  visit_data = make_request(
@@ -208,7 +212,7 @@ def enrich_leads_with_visits(df, start_date, end_date, max_rows=None, progress=g
208
  except Exception as e:
209
  print(f"Failed to enrich lead {lead_id}: {e}")
210
 
211
- if index % 5 == 0:
212
  progress(index / total, desc="Enriching...")
213
 
214
  return df
@@ -315,42 +319,51 @@ def build_trend(df, preset, grain, filter_values):
315
  return px.line(ts, x="period", y=val, markers=True, template="plotly_white", title=preset)
316
 
317
  # =====================================================
318
- # ADVANCED ANALYTICS (WITH SEARCH FILTER)
319
  # =====================================================
320
- def build_advanced_plots(df, search_lead_id=None, search_company=None):
321
  if df is None or df.empty:
322
  return None, None
323
 
324
- # --- FILTERING LOGIC ---
325
  filtered_df = df.copy()
326
-
327
  title_suffix = ""
328
 
329
- # 1. Filter by Lead ID (Exact Match)
330
  if search_lead_id and search_lead_id.strip():
331
  filtered_df = filtered_df[filtered_df["lead_id"] == search_lead_id.strip()]
332
  title_suffix = f" (Lead: {search_lead_id})"
333
 
334
- # 2. Filter by Company Name (Partial Match, Case Insensitive)
335
  if search_company and search_company.strip():
336
- # Handle NA values before string search
337
  filtered_df = filtered_df[filtered_df["company_name"].notna()]
338
  filtered_df = filtered_df[filtered_df["company_name"].str.contains(search_company, case=False, na=False)]
339
  title_suffix = f" (Company: {search_company})"
340
 
341
  if filtered_df.empty:
342
- # Return empty figures or message logic handled by returning None
343
  return go.Figure(layout=dict(title="No matching data found")), go.Figure(layout=dict(title="No matching data found"))
344
 
345
- # --- 1. SANKEY DIAGRAM ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
346
  flow_df = filtered_df.dropna(subset=["landing_page_path", "exit_page_path"])
347
 
348
  if flow_df.empty:
349
- sankey_fig = go.Figure(layout=dict(title="No valid Landing/Exit pages found for selection"))
350
  else:
351
  flow_counts = flow_df.groupby(["landing_page_path", "exit_page_path"]).size().reset_index(name="count")
352
 
353
- # If searching specific company, we show ALL their flows. Otherwise top 20.
354
  if not search_lead_id and not search_company:
355
  flow_counts = flow_counts.sort_values("count", ascending=False).head(20)
356
 
@@ -367,10 +380,10 @@ def build_advanced_plots(df, search_lead_id=None, search_company=None):
367
  )])
368
  sankey_fig.update_layout(title_text=f"User Flow: Landing โ†’ Exit{title_suffix}", font_size=10)
369
 
370
- # --- 2. HEATMAP ---
371
  temp_df = filtered_df.dropna(subset=["last_visit_date"]).copy()
372
  if temp_df.empty:
373
- heatmap_fig = go.Figure(layout=dict(title="No visit dates found for selection"))
374
  else:
375
  temp_df["day_name"] = temp_df["last_visit_date"].dt.day_name()
376
  temp_df["hour"] = temp_df["last_visit_date"].dt.hour
@@ -449,7 +462,7 @@ with gr.Blocks(title="Leadfeeder Pro Analytics") as demo:
449
  plot
450
  )
451
 
452
- # --- TAB 4: ADVANCED ANALYTICS (UPDATED WITH SEARCH) ---
453
  with gr.Tab("๐Ÿ”ฌ Advanced Analytics"):
454
  gr.Markdown("Visualize user behavior flows. Leave search blank to see aggregate Top 20 flows.")
455
 
@@ -463,8 +476,8 @@ with gr.Blocks(title="Leadfeeder Pro Analytics") as demo:
463
  sankey_plot = gr.Plot(label="User Flow (Sankey)")
464
  heatmap_plot = gr.Plot(label="Activity Heatmap")
465
 
466
- # Pass the new search inputs to the function
467
- btn_adv.click(build_advanced_plots, [df_state, search_lead, search_comp], [sankey_plot, heatmap_plot])
468
 
469
  # --- TAB 5: DEBUGGER ---
470
  with gr.Tab("๐Ÿ› ๏ธ Debugger"):
 
156
  print(f"๐Ÿ•ต๏ธ Deep enriching {total} rows ({start_date} to {end_date})...")
157
 
158
  for index, row in target_df.iterrows():
159
+ # Only enrich if data is missing
160
+ if row.get("landing_page_path") and row.get("exit_page_path"):
161
+ continue
162
+
163
  lead_id = row["lead_id"]
164
  try:
165
  visit_data = make_request(
 
212
  except Exception as e:
213
  print(f"Failed to enrich lead {lead_id}: {e}")
214
 
215
+ if max_rows and index % 5 == 0:
216
  progress(index / total, desc="Enriching...")
217
 
218
  return df
 
319
  return px.line(ts, x="period", y=val, markers=True, template="plotly_white", title=preset)
320
 
321
  # =====================================================
322
+ # ADVANCED ANALYTICS (WITH AUTO-ENRICHMENT)
323
  # =====================================================
324
+ def build_advanced_plots(df, search_lead_id, search_company, start_date, end_date):
325
  if df is None or df.empty:
326
  return None, None
327
 
328
+ # --- 1. FILTER ---
329
  filtered_df = df.copy()
 
330
  title_suffix = ""
331
 
 
332
  if search_lead_id and search_lead_id.strip():
333
  filtered_df = filtered_df[filtered_df["lead_id"] == search_lead_id.strip()]
334
  title_suffix = f" (Lead: {search_lead_id})"
335
 
 
336
  if search_company and search_company.strip():
 
337
  filtered_df = filtered_df[filtered_df["company_name"].notna()]
338
  filtered_df = filtered_df[filtered_df["company_name"].str.contains(search_company, case=False, na=False)]
339
  title_suffix = f" (Company: {search_company})"
340
 
341
  if filtered_df.empty:
 
342
  return go.Figure(layout=dict(title="No matching data found")), go.Figure(layout=dict(title="No matching data found"))
343
 
344
+ # --- 2. AUTO-ENRICHMENT ---
345
+ # Check if the filtered rows are missing landing/exit data.
346
+ # If so, fetch it immediately!
347
+ missing_data = filtered_df[filtered_df["landing_page_path"].isnull()]
348
+
349
+ if not missing_data.empty:
350
+ # We pass the subset to the enrich function
351
+ print(f"๐Ÿ”„ Auto-enriching {len(missing_data)} rows for visualization...")
352
+
353
+ # We need to update the original filtered_df with the new data
354
+ enriched_subset = enrich_leads_with_visits(missing_data, start_date, end_date)
355
+
356
+ # Update the rows in filtered_df using the enriched data
357
+ filtered_df.update(enriched_subset)
358
+
359
+ # --- 3. SANKEY DIAGRAM ---
360
  flow_df = filtered_df.dropna(subset=["landing_page_path", "exit_page_path"])
361
 
362
  if flow_df.empty:
363
+ sankey_fig = go.Figure(layout=dict(title="No visit data available for selected lead(s)"))
364
  else:
365
  flow_counts = flow_df.groupby(["landing_page_path", "exit_page_path"]).size().reset_index(name="count")
366
 
 
367
  if not search_lead_id and not search_company:
368
  flow_counts = flow_counts.sort_values("count", ascending=False).head(20)
369
 
 
380
  )])
381
  sankey_fig.update_layout(title_text=f"User Flow: Landing โ†’ Exit{title_suffix}", font_size=10)
382
 
383
+ # --- 4. HEATMAP ---
384
  temp_df = filtered_df.dropna(subset=["last_visit_date"]).copy()
385
  if temp_df.empty:
386
+ heatmap_fig = go.Figure(layout=dict(title="No visit dates found"))
387
  else:
388
  temp_df["day_name"] = temp_df["last_visit_date"].dt.day_name()
389
  temp_df["hour"] = temp_df["last_visit_date"].dt.hour
 
462
  plot
463
  )
464
 
465
+ # --- TAB 4: ADVANCED ANALYTICS ---
466
  with gr.Tab("๐Ÿ”ฌ Advanced Analytics"):
467
  gr.Markdown("Visualize user behavior flows. Leave search blank to see aggregate Top 20 flows.")
468
 
 
476
  sankey_plot = gr.Plot(label="User Flow (Sankey)")
477
  heatmap_plot = gr.Plot(label="Activity Heatmap")
478
 
479
+ # NOTE: Passed start/end dates so we can auto-enrich on the fly!
480
+ btn_adv.click(build_advanced_plots, [df_state, search_lead, search_comp, start, end], [sankey_plot, heatmap_plot])
481
 
482
  # --- TAB 5: DEBUGGER ---
483
  with gr.Tab("๐Ÿ› ๏ธ Debugger"):