mktgtech commited on
Commit
2171fbc
·
verified ·
1 Parent(s): 65f029c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +28 -81
app.py CHANGED
@@ -1,6 +1,4 @@
1
  import os
2
- import time
3
- import random
4
  import requests
5
  import pandas as pd
6
  import gradio as gr
@@ -25,23 +23,6 @@ HEADERS = {
25
  "Accept": "application/json"
26
  }
27
 
28
- # =====================================================
29
- # SAFE REQUEST (RATE LIMIT HANDLING)
30
- # =====================================================
31
- def safe_get(url, params=None, max_retries=5):
32
- for attempt in range(max_retries):
33
- r = requests.get(url, headers=HEADERS, params=params, timeout=30)
34
-
35
- if r.status_code == 429:
36
- sleep_time = (2 ** attempt) + random.uniform(0.5, 1.5)
37
- time.sleep(sleep_time)
38
- continue
39
-
40
- r.raise_for_status()
41
- return r
42
-
43
- raise RuntimeError("Leadfeeder API rate limit exceeded. Try smaller date range.")
44
-
45
  # =====================================================
46
  # DASHBOARD PRESETS
47
  # =====================================================
@@ -83,57 +64,26 @@ def authenticate(pwd):
83
  return True
84
 
85
  # =====================================================
86
- # VISITS → LANDING & EXIT PAGE (THROTTLED)
87
- # =====================================================
88
- def fetch_landing_exit_pages(lead_id, start_date, end_date):
89
- try:
90
- r = safe_get(
91
- f"{BASE_URL}/accounts/{ACCOUNT_ID}/leads/{lead_id}/visits",
92
- params={
93
- "start_date": start_date,
94
- "end_date": end_date,
95
- "page[size]": 50
96
- }
97
- )
98
-
99
- visits = r.json().get("data", [])
100
- if not visits:
101
- return None, None
102
-
103
- visits = sorted(visits, key=lambda v: v["attributes"].get("started_at", ""))
104
-
105
- first_route = visits[0]["attributes"].get("visit_route", [])
106
- last_route = visits[-1]["attributes"].get("visit_route", [])
107
-
108
- landing = first_route[0]["page_path"] if first_route else None
109
- exit_page = last_route[-1]["page_path"] if last_route else None
110
-
111
- # IMPORTANT: throttle visit-level calls
112
- time.sleep(0.25)
113
-
114
- return landing, exit_page
115
-
116
- except Exception:
117
- return None, None
118
-
119
- # =====================================================
120
- # DATA FETCH (COMPANY LEVEL – RATE SAFE)
121
  # =====================================================
122
  def fetch_company_data(start_date, end_date):
123
  page, rows = 1, []
124
 
125
  while True:
126
- r = safe_get(
127
  f"{BASE_URL}/accounts/{ACCOUNT_ID}/leads",
 
128
  params={
129
  "start_date": start_date,
130
  "end_date": end_date,
131
  "page[number]": page,
132
  "page[size]": PAGE_SIZE
133
- }
 
134
  )
135
-
136
  js = r.json()
 
137
  data = js.get("data", [])
138
  if not data:
139
  break
@@ -149,10 +99,6 @@ def fetch_company_data(start_date, end_date):
149
  loc_id = lead.get("relationships", {}).get("location", {}).get("data", {}).get("id")
150
  loc = loc_map.get(loc_id, {})
151
 
152
- landing, exit_page = fetch_landing_exit_pages(
153
- lead.get("id"), start_date, end_date
154
- )
155
-
156
  rows.append({
157
  "lead_id": lead.get("id"),
158
  "company_name": a.get("name"),
@@ -187,29 +133,25 @@ def fetch_company_data(start_date, end_date):
187
  "region": loc.get("region"),
188
  "city": loc.get("city"),
189
  "leadfeeder_url": a.get("view_in_leadfeeder"),
190
- "landing_page_path": landing,
191
- "exit_page_path": exit_page,
192
  })
193
 
194
  page += 1
195
- time.sleep(0.3) # IMPORTANT pagination throttle
196
 
197
  df = pd.DataFrame(rows)
198
  df["last_visit_date"] = pd.to_datetime(df["last_visit_date"], errors="coerce")
199
  return df
200
 
201
  # =====================================================
202
- # LOAD WRAPPER (NO CRASH)
203
  # =====================================================
204
  def load_data_with_preview(start_date, end_date):
205
- try:
206
- df = fetch_company_data(start_date, end_date)
207
- return df, df.head(500), f"✅ Loaded {len(df):,} companies"
208
- except Exception as e:
209
- return None, None, f"❌ {str(e)}"
210
 
211
  # =====================================================
212
- # EXPORT
213
  # =====================================================
214
  def export_excel(df):
215
  path = "/tmp/leadfeeder_company_data.xlsx"
@@ -234,7 +176,6 @@ def build_kpis(df):
234
  # =====================================================
235
  def build_dashboard(df, preset, top_n):
236
  dim, metric, agg = DASHBOARD_PRESETS[preset]
237
-
238
  if agg == "count":
239
  grouped = df.groupby(dim, dropna=False).size().reset_index(name="value")
240
  else:
@@ -244,7 +185,7 @@ def build_dashboard(df, preset, top_n):
244
  return px.bar(grouped, x=dim, y="value", template="plotly_white", title=preset)
245
 
246
  # =====================================================
247
- # TREND ENGINE (CHART + TABLE)
248
  # =====================================================
249
  def build_trend(df, preset, grain):
250
  metric, agg, segment = TREND_PRESETS[preset]
@@ -265,12 +206,10 @@ def build_trend(df, preset, grain):
265
 
266
  if segment:
267
  ts = df.groupby(["period", segment])[val].agg(agg).reset_index()
268
- fig = px.bar(ts, x="period", y=val, color=segment, template="plotly_white")
269
- return fig, ts
270
 
271
  ts = df.groupby("period")[val].agg(agg).reset_index()
272
- fig = px.bar(ts, x="period", y=val, template="plotly_white")
273
- return fig, ts
274
 
275
  # =====================================================
276
  # UI
@@ -285,17 +224,25 @@ with gr.Blocks(title="Leadfeeder Company-Level Analytics") as demo:
285
 
286
  with gr.Tabs():
287
 
 
288
  with gr.Tab("📋 Data"):
289
  start = gr.Textbox(value=(date.today() - timedelta(days=30)).isoformat())
290
  end = gr.Textbox(value=date.today().isoformat())
 
291
  load_btn = gr.Button("Load Data")
292
- preview = gr.Dataframe(interactive=True)
293
  download_btn = gr.Button("⬇️ Download Excel")
294
  download_file = gr.File()
295
 
296
- load_btn.click(load_data_with_preview, [start, end], [df_state, preview, status])
 
 
 
 
 
297
  download_btn.click(export_excel, df_state, download_file)
298
 
 
299
  with gr.Tab("📊 Dashboard"):
300
  with gr.Row():
301
  k1 = gr.Number(label="Total Companies")
@@ -313,12 +260,12 @@ with gr.Blocks(title="Leadfeeder Company-Level Analytics") as demo:
313
 
314
  gr.Button("Build View").click(build_dashboard, [df_state, preset, top_n], chart)
315
 
 
316
  with gr.Tab("📈 Trends"):
317
  trend_view = gr.Dropdown(choices=list(TREND_PRESETS.keys()))
318
  grain = gr.Radio(["Daily", "Weekly", "Monthly"], value="Daily")
319
  plot = gr.Plot()
320
- table = gr.Dataframe()
321
 
322
- gr.Button("Show Trend").click(build_trend, [df_state, trend_view, grain], [plot, table])
323
 
324
  demo.launch(server_name="0.0.0.0", server_port=7860, ssr_mode=False)
 
1
  import os
 
 
2
  import requests
3
  import pandas as pd
4
  import gradio as gr
 
23
  "Accept": "application/json"
24
  }
25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  # =====================================================
27
  # DASHBOARD PRESETS
28
  # =====================================================
 
64
  return True
65
 
66
  # =====================================================
67
+ # DATA FETCH (WORKING)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  # =====================================================
69
  def fetch_company_data(start_date, end_date):
70
  page, rows = 1, []
71
 
72
  while True:
73
+ r = requests.get(
74
  f"{BASE_URL}/accounts/{ACCOUNT_ID}/leads",
75
+ headers=HEADERS,
76
  params={
77
  "start_date": start_date,
78
  "end_date": end_date,
79
  "page[number]": page,
80
  "page[size]": PAGE_SIZE
81
+ },
82
+ timeout=30
83
  )
84
+ r.raise_for_status()
85
  js = r.json()
86
+
87
  data = js.get("data", [])
88
  if not data:
89
  break
 
99
  loc_id = lead.get("relationships", {}).get("location", {}).get("data", {}).get("id")
100
  loc = loc_map.get(loc_id, {})
101
 
 
 
 
 
102
  rows.append({
103
  "lead_id": lead.get("id"),
104
  "company_name": a.get("name"),
 
133
  "region": loc.get("region"),
134
  "city": loc.get("city"),
135
  "leadfeeder_url": a.get("view_in_leadfeeder"),
 
 
136
  })
137
 
138
  page += 1
 
139
 
140
  df = pd.DataFrame(rows)
141
  df["last_visit_date"] = pd.to_datetime(df["last_visit_date"], errors="coerce")
142
  return df
143
 
144
  # =====================================================
145
+ # LOAD WRAPPER (STATE SAFE)
146
  # =====================================================
147
  def load_data_with_preview(start_date, end_date):
148
+ df = fetch_company_data(start_date, end_date)
149
+ preview = df.head(500)
150
+ status = f"✅ Loaded **{len(df):,} companies** (showing first 500 rows)"
151
+ return df, preview, status
 
152
 
153
  # =====================================================
154
+ # EXCEL EXPORT
155
  # =====================================================
156
  def export_excel(df):
157
  path = "/tmp/leadfeeder_company_data.xlsx"
 
176
  # =====================================================
177
  def build_dashboard(df, preset, top_n):
178
  dim, metric, agg = DASHBOARD_PRESETS[preset]
 
179
  if agg == "count":
180
  grouped = df.groupby(dim, dropna=False).size().reset_index(name="value")
181
  else:
 
185
  return px.bar(grouped, x=dim, y="value", template="plotly_white", title=preset)
186
 
187
  # =====================================================
188
+ # TREND ENGINE
189
  # =====================================================
190
  def build_trend(df, preset, grain):
191
  metric, agg, segment = TREND_PRESETS[preset]
 
206
 
207
  if segment:
208
  ts = df.groupby(["period", segment])[val].agg(agg).reset_index()
209
+ return px.line(ts, x="period", y=val, color=segment, template="plotly_white", title=preset)
 
210
 
211
  ts = df.groupby("period")[val].agg(agg).reset_index()
212
+ return px.line(ts, x="period", y=val, markers=True, template="plotly_white", title=preset)
 
213
 
214
  # =====================================================
215
  # UI
 
224
 
225
  with gr.Tabs():
226
 
227
+ # ================= DATA =================
228
  with gr.Tab("📋 Data"):
229
  start = gr.Textbox(value=(date.today() - timedelta(days=30)).isoformat())
230
  end = gr.Textbox(value=date.today().isoformat())
231
+
232
  load_btn = gr.Button("Load Data")
233
+ preview_table = gr.Dataframe(interactive=True)
234
  download_btn = gr.Button("⬇️ Download Excel")
235
  download_file = gr.File()
236
 
237
+ load_btn.click(
238
+ load_data_with_preview,
239
+ [start, end],
240
+ [df_state, preview_table, status]
241
+ )
242
+
243
  download_btn.click(export_excel, df_state, download_file)
244
 
245
+ # ================= DASHBOARD =================
246
  with gr.Tab("📊 Dashboard"):
247
  with gr.Row():
248
  k1 = gr.Number(label="Total Companies")
 
260
 
261
  gr.Button("Build View").click(build_dashboard, [df_state, preset, top_n], chart)
262
 
263
+ # ================= TRENDS =================
264
  with gr.Tab("📈 Trends"):
265
  trend_view = gr.Dropdown(choices=list(TREND_PRESETS.keys()))
266
  grain = gr.Radio(["Daily", "Weekly", "Monthly"], value="Daily")
267
  plot = gr.Plot()
 
268
 
269
+ gr.Button("Show Trend").click(build_trend, [df_state, trend_view, grain], plot)
270
 
271
  demo.launch(server_name="0.0.0.0", server_port=7860, ssr_mode=False)