stackConsult commited on
Commit
89ae4ff
Β·
verified Β·
1 Parent(s): a39b743

Create docs/DATA_ENRICHMENT.md

Browse files
Files changed (1) hide show
  1. docs/DATA_ENRICHMENT.md +480 -0
docs/DATA_ENRICHMENT.md ADDED
@@ -0,0 +1,480 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Data Enrichment Module Documentation
2
+
3
+ ## Overview
4
+
5
+ The `data_enrichment.py` module provides comprehensive contact and lead enrichment capabilities for the StrategyStack platform. It integrates 14 different data sources through RapidAPI to collect, enrich, and cache contact information.
6
+
7
+ ## Features
8
+
9
+ ### πŸ”Œ Multi-Provider Integration
10
+ - **LinkedIn APIs** (4 providers with fallback)
11
+ - **Apollo.io** - B2B contact enrichment
12
+ - **Social Media** - Twitter & Facebook profile data
13
+ - **Mediafy API** - Media and social data
14
+ - **Google Search** - Web search enrichment
15
+ - **LetScrape** - Local business data & website contacts
16
+
17
+ ### πŸ’Ύ Intelligent Caching
18
+ - Per-user data isolation (`/data/users/{username}/enrichment_cache/`)
19
+ - 30-day cache TTL
20
+ - Automatic cache invalidation
21
+ - Privacy-first design - users own their data
22
+
23
+ ### πŸ”„ Fallback & Redundancy
24
+ - Automatic failover between providers
25
+ - Graceful error handling
26
+ - Partial data return on API failures
27
+
28
+ ## Architecture
29
+
30
+ ```
31
+ DataEnrichmentManager
32
+ β”œβ”€β”€ API Keys Management (11 secrets)
33
+ β”œβ”€β”€ Request Handler (rate limiting, retries)
34
+ β”œβ”€β”€ Cache Manager (read/write/invalidate)
35
+ └── Enrichment Methods
36
+ β”œβ”€β”€ LinkedIn Profile
37
+ β”œβ”€β”€ Company Data
38
+ β”œβ”€β”€ Apollo.io
39
+ β”œβ”€β”€ Social Media
40
+ β”œβ”€β”€ Local Business
41
+ └── Website Contacts
42
+ ```
43
+
44
+ ## Installation & Setup
45
+
46
+ ### 1. Environment Variables
47
+
48
+ Add the following secrets to your Hugging Face Space:
49
+
50
+ ```bash
51
+ RAPIDAPI_KEY_LINKEDIN_FRESH
52
+ RAPIDAPI_KEY_LINKEDIN_ROCKAPIS
53
+ RAPIDAPI_KEY_LISCRAPER
54
+ RAPIDAPI_KEY_LINKEDIN_SCRAPER
55
+ RAPIDAPI_KEY_APOLLO
56
+ RAPIDAPI_KEY_MEDIAFY
57
+ RAPIDAPI_KEY_TWITTER
58
+ RAPIDAPI_KEY_FACEBOOK
59
+ RAPIDAPI_KEY_GOOGLE
60
+ RAPIDAPI_KEY_LETSCRAPE
61
+ ```
62
+
63
+ ### 2. Import Module
64
+
65
+ ```python
66
+ from data_enrichment import DataEnrichmentManager, enrich_contact
67
+
68
+ # Initialize manager
69
+ manager = DataEnrichmentManager(username="user123")
70
+ ```
71
+
72
+ ## Usage Examples
73
+
74
+ ### Basic Contact Enrichment
75
+
76
+ ```python
77
+ # Enrich a single contact
78
+ contact_data = {
79
+ 'name': 'John Doe',
80
+ 'email': 'john@example.com',
81
+ 'linkedin_url': 'https://linkedin.com/in/johndoe',
82
+ 'domain': 'example.com'
83
+ }
84
+
85
+ result = manager.enrich_contact_full(contact_data)
86
+
87
+ print(f"Enriched from {result['total_sources']} sources")
88
+ print(f"Sources used: {result['sources']}")
89
+ ```
90
+
91
+ ### LinkedIn Profile Enrichment
92
+
93
+ ```python
94
+ # Get LinkedIn profile data (with fallback)
95
+ profile = manager.enrich_linkedin_profile(
96
+ 'https://linkedin.com/in/johndoe'
97
+ )
98
+
99
+ if profile:
100
+ print(f"Name: {profile.get('name')}")
101
+ print(f"Title: {profile.get('title')}")
102
+ print(f"Company: {profile.get('company')}")
103
+ ```
104
+
105
+ ### Company Enrichment
106
+
107
+ ```python
108
+ # Enrich company by domain
109
+ company = manager.enrich_company('example.com')
110
+
111
+ if company:
112
+ print(f"Company: {company.get('name')}")
113
+ print(f"Industry: {company.get('industry')}")
114
+ print(f"Size: {company.get('employee_count')}")
115
+ ```
116
+
117
+ ### LetScrape: Local Business Data
118
+
119
+ ```python
120
+ # Search for local businesses
121
+ businesses = manager.scrape_local_business(
122
+ query='pizza restaurants',
123
+ location='New York, NY',
124
+ limit=20
125
+ )
126
+
127
+ for business in businesses.get('data', []):
128
+ print(f"Name: {business.get('name')}")
129
+ print(f"Address: {business.get('address')}")
130
+ print(f"Phone: {business.get('phone')}")
131
+ print(f"Rating: {business.get('rating')}")
132
+ ```
133
+
134
+ ### LetScrape: Website Contacts
135
+
136
+ ```python
137
+ # Extract contacts from a website
138
+ contacts = manager.scrape_website_contacts('example.com')
139
+
140
+ if contacts:
141
+ print(f"Emails: {contacts.get('emails', [])}")
142
+ print(f"Phones: {contacts.get('phones', [])}")
143
+ print(f"Social: {contacts.get('social_links', {})}")
144
+ ```
145
+
146
+ ### Batch Enrichment
147
+
148
+ ```python
149
+ # Enrich multiple contacts
150
+ contacts = [
151
+ {'name': 'John Doe', 'email': 'john@example.com'},
152
+ {'name': 'Jane Smith', 'domain': 'acme.com'}
153
+ ]
154
+
155
+ for contact in contacts:
156
+ enriched = manager.enrich_contact_full(contact)
157
+ print(f"Enriched {contact['name']} from {enriched['total_sources']} sources")
158
+ ```
159
+
160
+ ## API Methods Reference
161
+
162
+ ### Core Methods
163
+
164
+ #### `__init__(username: str)`
165
+ Initialize the enrichment manager for a specific user.
166
+
167
+ **Parameters:**
168
+ - `username` (str): User identifier for data isolation
169
+
170
+ #### `enrich_contact_full(contact_data: Dict) -> Dict`
171
+ Perform comprehensive enrichment using all available sources.
172
+
173
+ **Parameters:**
174
+ - `contact_data` (dict): Contact information
175
+ - `name` (str, optional)
176
+ - `email` (str, optional)
177
+ - `linkedin_url` (str, optional)
178
+ - `domain` (str, optional)
179
+ - `company` (str, optional)
180
+ - `location` (str, optional)
181
+ - `twitter_username` (str, optional)
182
+ - `facebook_id` (str, optional)
183
+
184
+ **Returns:**
185
+ ```python
186
+ {
187
+ 'original': {...}, # Original input data
188
+ 'enrichments': { # Enriched data by source
189
+ 'linkedin': {...},
190
+ 'apollo': {...},
191
+ 'company': {...},
192
+ 'website_contacts': {...},
193
+ 'local_business': {...}
194
+ },
195
+ 'sources': ['linkedin', 'apollo', ...], # Sources used
196
+ 'total_sources': 5, # Count of successful enrichments
197
+ 'enriched_at': '2025-11-06T14:00:00' # Timestamp
198
+ }
199
+ ```
200
+
201
+ ### LinkedIn Methods
202
+
203
+ #### `enrich_linkedin_profile(linkedin_url: str) -> Optional[Dict]`
204
+ Enrich LinkedIn profile with automatic fallback across 4 providers.
205
+
206
+ #### `enrich_company(domain: str) -> Optional[Dict]`
207
+ Get company information from LinkedIn by domain.
208
+
209
+ ### Apollo.io
210
+
211
+ #### `enrich_with_apollo(email: str = None, domain: str = None) -> Optional[Dict]`
212
+ Enrich contact using Apollo.io B2B database.
213
+
214
+ ### Social Media
215
+
216
+ #### `enrich_twitter_profile(username: str) -> Optional[Dict]`
217
+ Get Twitter profile data.
218
+
219
+ #### `enrich_facebook_profile(profile_id: str) -> Optional[Dict]`
220
+ Get Facebook profile data.
221
+
222
+ ### Search & Media
223
+
224
+ #### `search_google(query: str, num_results: int = 10) -> Optional[Dict]`
225
+ Perform Google search for contact information.
226
+
227
+ #### `enrich_with_mediafy(query: str) -> Optional[Dict]`
228
+ Get media and social data from Mediafy API.
229
+
230
+ ### LetScrape Methods
231
+
232
+ #### `scrape_local_business(query: str, location: str = None, limit: int = 20) -> Optional[Dict]`
233
+ Scrape local business data from Google Maps.
234
+
235
+ **Parameters:**
236
+ - `query` (str): Business search query (e.g., "pizza restaurants")
237
+ - `location` (str, optional): Geographic location
238
+ - `limit` (int): Maximum results (default: 20)
239
+
240
+ **Returns:**
241
+ ```python
242
+ {
243
+ 'data': [
244
+ {
245
+ 'name': 'Business Name',
246
+ 'address': '123 Main St',
247
+ 'phone': '+1234567890',
248
+ 'email': 'contact@business.com',
249
+ 'website': 'https://business.com',
250
+ 'rating': 4.5,
251
+ 'review_count': 150,
252
+ 'category': 'Restaurant',
253
+ 'hours': {...}
254
+ }
255
+ ]
256
+ }
257
+ ```
258
+
259
+ #### `scrape_website_contacts(domain: str) -> Optional[Dict]`
260
+ Extract emails, phone numbers, and social links from a website.
261
+
262
+ **Parameters:**
263
+ - `domain` (str): Website domain (e.g., "example.com")
264
+
265
+ **Returns:**
266
+ ```python
267
+ {
268
+ 'emails': ['contact@example.com', 'info@example.com'],
269
+ 'phones': ['+1234567890'],
270
+ 'social_links': {
271
+ 'facebook': 'https://facebook.com/example',
272
+ 'linkedin': 'https://linkedin.com/company/example',
273
+ 'twitter': 'https://twitter.com/example',
274
+ 'instagram': 'https://instagram.com/example'
275
+ }
276
+ }
277
+ ```
278
+
279
+ ### Utility Methods
280
+
281
+ #### `get_enrichment_stats() -> Dict`
282
+ Get cache statistics and API usage information.
283
+
284
+ **Returns:**
285
+ ```python
286
+ {
287
+ 'cache_directory': '/data/users/user123/enrichment_cache',
288
+ 'cached_profiles': 45,
289
+ 'cache_types': {
290
+ 'linkedin': 15,
291
+ 'company': 10,
292
+ 'apollo': 12,
293
+ 'website_contacts': 8
294
+ },
295
+ 'configured_apis': ['linkedin_fresh', 'apollo', 'letscrape'],
296
+ 'total_apis': 10
297
+ }
298
+ ```
299
+
300
+ ## Data Privacy & Security
301
+
302
+ ### User Data Isolation
303
+ - Each user has separate cache directory
304
+ - No cross-user data access
305
+ - Users own their enrichment data
306
+
307
+ ### Cache Management
308
+ - 30-day automatic expiration
309
+ - Stored in user-specific directories
310
+ - Can be manually cleared
311
+
312
+ ### API Key Security
313
+ - All keys stored as HuggingFace Secrets
314
+ - Never exposed in logs or responses
315
+ - Separate keys per API provider
316
+
317
+ ## Performance Optimization
318
+
319
+ ### Caching Strategy
320
+ 1. Check cache first (instant response)
321
+ 2. If cache miss, call API
322
+ 3. Store result in cache
323
+ 4. Return data
324
+
325
+ ### Fallback Logic
326
+ ```python
327
+ Providers = [Primary, Secondary, Tertiary, Fallback]
328
+ for provider in Providers:
329
+ try:
330
+ data = provider.fetch()
331
+ if data: return data
332
+ except:
333
+ continue
334
+ return None
335
+ ```
336
+
337
+ ### Rate Limiting
338
+ - 30-second timeout per request
339
+ - Automatic retry on failures
340
+ - Respects API provider limits
341
+
342
+ ## Error Handling
343
+
344
+ All methods return `None` on failure and log errors:
345
+
346
+ ```python
347
+ try:
348
+ result = manager.enrich_linkedin_profile(url)
349
+ if result:
350
+ # Success
351
+ else:
352
+ # Failed - check logs
353
+ except Exception as e:
354
+ # Handle exception
355
+ logger.error(f"Enrichment failed: {e}")
356
+ ```
357
+
358
+ ## Integration Examples
359
+
360
+ ### With Contact Management
361
+
362
+ ```python
363
+ def create_contact(user, contact_data):
364
+ # Create contact
365
+ contact = Contact.create(**contact_data)
366
+
367
+ # Enrich asynchronously
368
+ manager = DataEnrichmentManager(user.username)
369
+ enriched = manager.enrich_contact_full(contact_data)
370
+
371
+ # Store enrichment
372
+ contact.enrichment_data = enriched
373
+ contact.save()
374
+
375
+ return contact
376
+ ```
377
+
378
+ ### With Outreach Agent
379
+
380
+ ```python
381
+ def prepare_outreach(contact):
382
+ # Enrich contact before outreach
383
+ manager = DataEnrichmentManager(current_user)
384
+ enriched = manager.enrich_contact_full({
385
+ 'email': contact.email,
386
+ 'linkedin_url': contact.linkedin_url,
387
+ 'domain': contact.company_domain
388
+ })
389
+
390
+ # Use enriched data for personalization
391
+ if enriched['total_sources'] > 0:
392
+ contact.enriched = True
393
+ contact.enrichment_score = enriched['total_sources']
394
+
395
+ return enriched
396
+ ```
397
+
398
+ ## Troubleshooting
399
+
400
+ ### Common Issues
401
+
402
+ **Issue: No data returned**
403
+ - Check API keys are configured
404
+ - Verify network connectivity
405
+ - Check rate limits
406
+
407
+ **Issue: Slow responses**
408
+ - Cache may be cold (first request)
409
+ - API provider may be slow
410
+ - Check timeout settings
411
+
412
+ **Issue: Missing enrichments**
413
+ - Some providers may not have data
414
+ - Check logs for API errors
415
+ - Verify input data format
416
+
417
+ ### Debug Mode
418
+
419
+ ```python
420
+ import logging
421
+ logging.basicConfig(level=logging.DEBUG)
422
+
423
+ manager = DataEnrichmentManager(username)
424
+ result = manager.enrich_contact_full(contact_data)
425
+ # Check logs for detailed information
426
+ ```
427
+
428
+ ## API Provider Details
429
+
430
+ ### RapidAPI Configuration
431
+
432
+ All APIs are accessed through RapidAPI:
433
+ - Host: `*.p.rapidapi.com`
434
+ - Authentication: `x-rapidapi-key` header
435
+ - Format: JSON
436
+ - Protocol: HTTPS
437
+
438
+ ### Provider URLs
439
+
440
+ - **LinkedIn Fresh**: `fresh-linkedin-profile-data.p.rapidapi.com`
441
+ - **LinkedIn RockAPIs**: `linkedin-data-api.p.rapidapi.com`
442
+ - **LI Data Scraper**: `li-data-scraper.p.rapidapi.com`
443
+ - **LinkedIn Scraper**: `linkedin-data-scraper.p.rapidapi.com`
444
+ - **Apollo.io**: `apollo-io-no-cookies-required.p.rapidapi.com`
445
+ - **Mediafy**: `mediafy-api.p.rapidapi.com`
446
+ - **Twitter**: `twitter241.p.rapidapi.com`
447
+ - **Facebook**: `facebook-scraper3.p.rapidapi.com`
448
+ - **Google**: `google-search74.p.rapidapi.com`
449
+ - **LetScrape Business**: `local-business-data.p.rapidapi.com`
450
+ - **LetScrape Contacts**: `website-contacts-scraper.p.rapidapi.com`
451
+
452
+ ## Changelog
453
+
454
+ ### Version 2.0.0 (2025-11-06)
455
+ - ✨ Added LetScrape Local Business Data API
456
+ - ✨ Added LetScrape Website Contacts Scraper API
457
+ - πŸ”„ Enhanced fallback logic
458
+ - πŸ“š Comprehensive documentation
459
+ - πŸ› Bug fixes and improvements
460
+
461
+ ### Version 1.0.0 (2025-11-05)
462
+ - πŸŽ‰ Initial release
463
+ - LinkedIn enrichment (4 providers)
464
+ - Apollo.io integration
465
+ - Social media enrichment
466
+ - Caching system
467
+ - Per-user data isolation
468
+
469
+ ## Support & Contact
470
+
471
+ For issues or questions:
472
+ - Check logs in `/data/users/{username}/enrichment_cache/`
473
+ - Review API provider documentation
474
+ - Contact StrategyStack support
475
+
476
+ ---
477
+
478
+ **Last Updated:** November 6, 2025
479
+ **Version:** 2.0.0
480
+ **Maintainer:** StrategyStack Team