ps1811 commited on
Commit
b663ee4
·
1 Parent(s): 10d99e1

Sample data creation pipeline added

Browse files
app/ads1/merge.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+
3
+ def merge_dfs(real_dfs: dict, sample_dfs: dict) -> dict:
4
+ """
5
+ Merge real Google Ads data with synthetic sample data.
6
+ Keeps schema identical and adds source tracking.
7
+ """
8
+
9
+ merged = {}
10
+
11
+ for key in real_dfs.keys():
12
+ real_df = real_dfs.get(key)
13
+ sample_df = sample_dfs.get(key)
14
+
15
+ # If both exist
16
+ if real_df is not None and sample_df is not None:
17
+ real_df = real_df.copy()
18
+ sample_df = sample_df.copy()
19
+
20
+ real_df["source"] = "real"
21
+ sample_df["source"] = "sample"
22
+
23
+ # Align columns safely
24
+ for col in real_df.columns:
25
+ if col not in sample_df.columns:
26
+ sample_df[col] = None
27
+
28
+ for col in sample_df.columns:
29
+ if col not in real_df.columns:
30
+ real_df[col] = None
31
+
32
+ # Ensure same column order
33
+ sample_df = sample_df[real_df.columns]
34
+
35
+ merged[key] = pd.concat([real_df, sample_df], ignore_index=True)
36
+
37
+ elif real_df is not None:
38
+ real_df = real_df.copy()
39
+ real_df["source"] = "real"
40
+ merged[key] = real_df
41
+
42
+ elif sample_df is not None:
43
+ sample_df = sample_df.copy()
44
+ sample_df["source"] = "sample"
45
+ merged[key] = sample_df
46
+
47
+ return merged
app/ads1/sample_data.py ADDED
@@ -0,0 +1,218 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import pandas as pd
3
+
4
+ def _rand(low, high, size):
5
+ return np.random.randint(low, high, size)
6
+
7
+ def _money(low, high, size):
8
+ return np.round(np.random.uniform(low, high, size), 2)
9
+
10
+ def _pick(arr, size):
11
+ return np.random.choice(arr, size)
12
+
13
+ def generate_sample_campaigns():
14
+ campaigns = [
15
+ {
16
+ "id": 1001,
17
+ "name": "Nursery Admissions 2026",
18
+ "status": "ENABLED",
19
+ "impressions": 120000,
20
+ "clicks": 8500,
21
+ "cost": 12000.0,
22
+ "ctr": 7.08,
23
+ "conversions": 420,
24
+ },
25
+ {
26
+ "id": 1002,
27
+ "name": "Playgroup Enrollment Campaign",
28
+ "status": "ENABLED",
29
+ "impressions": 90000,
30
+ "clicks": 6200,
31
+ "cost": 8000.0,
32
+ "ctr": 6.88,
33
+ "conversions": 310,
34
+ },
35
+ {
36
+ "id": 1003,
37
+ "name": "Summer Camp 2026",
38
+ "status": "ENABLED",
39
+ "impressions": 150000,
40
+ "clicks": 4000,
41
+ "cost": 7000.0,
42
+ "ctr": 2.66,
43
+ "conversions": 180,
44
+ },
45
+ {
46
+ "id": 1004,
47
+ "name": "School Tour Booking Campaign",
48
+ "status": "ENABLED",
49
+ "impressions": 60000,
50
+ "clicks": 2200,
51
+ "cost": 3500.0,
52
+ "ctr": 3.66,
53
+ "conversions": 140,
54
+ },
55
+ ]
56
+
57
+ return pd.DataFrame(campaigns)
58
+
59
+ # 2. SEARCH TERMS
60
+ def generate_sample_search_terms():
61
+ positive_intent = [
62
+ "nursery admission near me",
63
+ "best preschool in Yelahanka",
64
+ "play school admission 2026",
65
+ "kg admission Bangalore",
66
+ "preschool fees near me",
67
+ "daycare near Yelahanka",
68
+ ]
69
+
70
+ negative_intent = [
71
+ "free babysitting jobs",
72
+ "toy store near me",
73
+ "kids games online",
74
+ "montessori certification course",
75
+ "child psychology course",
76
+ "teaching jobs preschool",
77
+ ]
78
+
79
+ campaigns = [
80
+ "Nursery Admissions 2026",
81
+ "Playgroup Enrollment Campaign",
82
+ "Summer Camp 2026",
83
+ "School Tour Booking Campaign",
84
+ ]
85
+
86
+ rows = []
87
+
88
+ for campaign in campaigns:
89
+ for term in positive_intent + negative_intent:
90
+
91
+ clicks = np.random.randint(5, 250)
92
+ impressions = clicks * np.random.randint(5, 60)
93
+ cost = round(clicks * np.random.uniform(0.5, 4.0), 2)
94
+
95
+ # realistic conversion logic
96
+ if term in positive_intent:
97
+ conversions = np.random.randint(1, 25)
98
+ else:
99
+ conversions = np.random.choice([0, 0, 0, 1])
100
+
101
+ rows.append({
102
+ "search_term": term,
103
+ "campaign_name": campaign,
104
+ "clicks": clicks,
105
+ "impressions": impressions,
106
+ "cost": cost,
107
+ "conversions": conversions,
108
+ })
109
+
110
+ return pd.DataFrame(rows)
111
+
112
+ # 3. KEYWORDS
113
+ def generate_sample_keywords():
114
+ keywords = [
115
+ "preschool admission",
116
+ "nursery school near me",
117
+ "play school Bangalore",
118
+ "kg admission",
119
+ "daycare Yelahanka",
120
+ "best preschool",
121
+ ]
122
+
123
+ campaigns = [
124
+ "Nursery Admissions 2026",
125
+ "Playgroup Enrollment Campaign",
126
+ "Summer Camp 2026",
127
+ "School Tour Booking Campaign",
128
+ ]
129
+
130
+ rows = []
131
+
132
+ for campaign in campaigns:
133
+ for kw in keywords:
134
+
135
+ clicks = np.random.randint(50, 500)
136
+ impressions = clicks * np.random.randint(10, 80)
137
+ cost = round(clicks * np.random.uniform(0.8, 5.0), 2)
138
+
139
+ # realistic conversion behavior
140
+ if "admission" in kw or "preschool" in kw:
141
+ conversions = np.random.randint(5, 40)
142
+ else:
143
+ conversions = np.random.choice([0, 0, 1, 2, 3])
144
+
145
+ ctr = round((clicks / impressions) * 100, 2)
146
+
147
+ rows.append({
148
+ "campaign_name": campaign,
149
+ "keyword": kw,
150
+ "clicks": clicks,
151
+ "impressions": impressions,
152
+ "cost": cost,
153
+ "conversions": conversions,
154
+ "ctr": ctr,
155
+ })
156
+
157
+ return pd.DataFrame(rows)
158
+
159
+ # ==================================================
160
+ # 4. HOURLY (OPTIONAL BUT MATCHES REAL STRUCTURE)
161
+ # ==================================================
162
+
163
+ def generate_sample_hourly():
164
+ hours = list(range(24))
165
+ rows = []
166
+
167
+ for campaign in [
168
+ "Nursery Admissions 2026",
169
+ "Playgroup Enrollment Campaign",
170
+ "Summer Camp 2026",
171
+ "School Tour Booking Campaign",
172
+ ]:
173
+ for h in hours:
174
+ clicks = np.random.randint(0, 80)
175
+ impressions = clicks * np.random.randint(5, 30)
176
+ cost = round(clicks * np.random.uniform(0.2, 3.0), 2)
177
+
178
+ rows.append({
179
+ "date": "2026-06-01",
180
+ "hour": h,
181
+ "clicks": clicks,
182
+ "impressions": impressions,
183
+ "cost": cost,
184
+ })
185
+
186
+ return pd.DataFrame(rows)
187
+
188
+
189
+ # ==================================================
190
+ # 5. GEO (OPTIONAL BUT MATCHES REAL STRUCTURE)
191
+ # ==================================================
192
+
193
+ def generate_sample_geo():
194
+ countries = ["IN", "AE", "US"]
195
+ rows = []
196
+
197
+ for c in countries:
198
+ rows.append({
199
+ "country_id": c,
200
+ "clicks": np.random.randint(500, 5000),
201
+ "impressions": np.random.randint(10000, 100000),
202
+ "cost": round(np.random.uniform(500, 5000), 2),
203
+ })
204
+
205
+ return pd.DataFrame(rows)
206
+
207
+
208
+ # 4. MASTER GENERATOR
209
+ def generate_sample_dfs():
210
+ return {
211
+ "campaigns": generate_sample_campaigns(),
212
+ "search_terms": generate_sample_search_terms(),
213
+ "keywords": generate_sample_keywords(),
214
+ "hourly": generate_sample_hourly(),
215
+ "geo": generate_sample_geo(),
216
+ "devices": pd.DataFrame(), # optional placeholder
217
+ "recommendations": pd.DataFrame(), # optional placeholder
218
+ }
app/controller/session_loader.py CHANGED
@@ -7,6 +7,9 @@ import pickle
7
 
8
  import pandas as pd
9
  from app.ads1.fetch_ads_data import fetch_all_data, to_dataframes
 
 
 
10
  # from dotenv import load_dotenv
11
  # load_dotenv()
12
 
@@ -33,8 +36,11 @@ def load_google_ads_data(force_refresh=False):
33
  return pickle.load(f)
34
 
35
  print("🌐 Disk cache expired or missing. Fetching live Google Ads data...")
36
- raw = fetch_all_data(customer_id)
37
- dfs = to_dataframes(raw)
 
 
 
38
 
39
  # Save to disk cache safely
40
  with open(CACHE_FILE, "wb") as f:
 
7
 
8
  import pandas as pd
9
  from app.ads1.fetch_ads_data import fetch_all_data, to_dataframes
10
+ from app.ads1.merge import merge_dfs
11
+ from app.ads1.sample_data import generate_sample_dfs
12
+
13
  # from dotenv import load_dotenv
14
  # load_dotenv()
15
 
 
36
  return pickle.load(f)
37
 
38
  print("🌐 Disk cache expired or missing. Fetching live Google Ads data...")
39
+ real_raw = fetch_all_data(customer_id)
40
+ real_dfs = to_dataframes(real_raw)
41
+
42
+ sample_dfs = generate_sample_dfs()
43
+ dfs = merge_dfs(real_dfs, sample_dfs)
44
 
45
  # Save to disk cache safely
46
  with open(CACHE_FILE, "wb") as f: