Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions skills/hubspot-leadgenius/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# 🚀 LeadGenius to HubSpot High-Speed Synchronization Pipeline

A robust, fully-automated Python integration pipeline designed to extract highly enriched leads from the [LeadGenius Automation API](https://www.leadgenius.com/) and dynamically inject them into [HubSpot CRM](https://www.hubspot.com/).

This repository serves as a fully functional CLI toolkit for RevOps engineers and SDR Managers looking to bypass manual CSV uploads and securely transfer rich, JSON-nested AI data attributes (scores, logic recommendations, complex company overviews, and HTML-formatted outreach emails) directly into custom CRM properties.

---

## ⚡ Core Features

* **Global Rate-Limit Bypassing:** Utilizes native LeadGenius Administrative Tokens (`X-Admin-Key`) to securely and exponentially pull thousands of leads without facing the standard `HTTP 429 Too Many Requests` API bottlenecks.
* **Dynamic CRM Schema Creation:** Intelligently pings the HubSpot `v3/properties` schema endpoints on execution. It dynamically establishes a dedicated "LeadGenius AI Insights" nested property group and creates 40+ custom properties natively under the `lg_` prefix exactly where they do not already exist.
* **Idempotent Data Upserts:** Completely immune to duplication bugs. The pipeline batches lead profiles into 100-contact arrays and utilizes the HubSpot High-Volume Import API natively leveraging standard `Email` fields as programmatic uniqueness triggers.
* **Deep JSON Payload Extraction:** Natively unpacks the highly-complex AI strings and `capture_all` arrays. Translates deeply nested `{"subject": "...", "content": "<br>"}` objects into pristine readable HubSpot text areas without HTML artifacts.
* **Integer Force Formatting:** Automatically intercepts and cleans faulty string arrays (e.g., converting `"72.0"` natively to integer `'72'`) so that HubSpot filtering schemas operate reliably.

---

## 🛠 Prerequisites & Installation

### 1. Environment Setup

Ensure you have Python 3 installed. Navigate to the project root and install the basic required HTTP dependencies:

```bash
pip install requests python-dotenv
```

### 2. Required Authentication Variables (.env)

Create a strict `.env` file at the root of the project structure. Do not commit this file to version control.

```env
# Standard LeadGenius Token
LGP_API_KEY=your_standard_lg_token

# Administrative Token used explicitly for Global Limit Bypass
LGP_MASTER_KEY=your_x_admin_key_for_unlimited_speed

# HubSpot Private App Authentication Link
HUBSPOT_API_KEY=your_private_app_bearer_token
```

#### How to obtain your HubSpot Token
1. In HubSpot, navigate to **Settings > Integrations > Private Apps**.
2. Click **Create Private App** and name it `LeadGenius Sync`.
3. Under **Scopes**, absolutely ensure you grant:
- `crm.objects.contacts.read` & `write`
- `crm.schemas.contacts.read` & `write`
4. Copy your generated **Access Token**.

---

## 🚀 Usage Guide

### Full Database Synchronization
To completely orchestrate a global synchronization of your entire campaign array straight into your existing CRM layout:

```bash
python3 scripts/lg_full_to_hs.py
```

**Step-by-step Execution Flow:**
1. **Schema Check:** Quickly queries your portal schemas, automatically injecting custom properties (`lg_company_description`, `lg_ai_score`, etc.) safely into a dedicated folder without destructive overrides.
2. **Metadata Fetching:** Resolves thousands of Target Entity IDs sequentially.
3. **Payload Download:** Utilizing your `.env` master keys, caches fully-enriched JSON details for every Target Entity securely into local OS memory matrices.
4. **Mass Upload:** Formats arrays and blasts the cleaned, parsed leads directly to the CRM Batch injection endpoints seamlessly!

---

## 👔 Optimizing SDR Workflows inside HubSpot

Due to HubSpot API limitations prohibiting external scripts from rewriting UI View interfaces, SDR Administrators must manually execute the following layout tweaks to extract maximum value from this synchronization:

1. **The SDR View (Table Layout):** Navigate to **Contacts > Add View > Create New View**. Surface target columns: `Mobile Phone`, `LG AI Score`, `LG Recommendation`, `LG LinkedIn URL`. Save this View as a Shared Entity so the entire outbound floor can execute down the pipeline flawlessly.
2. **The Sales Dashboard Sidebar (Record Level):** Click the Settings gear, go to **Objects > Contacts > Record Customization**, and edit the **Left Sidebar**. Create a structural component titled **LeadGenius AI Insights** and pin all `lg_` properties directly to the top so Sales Development Reps don't have to scroll to view AI analytics during live calls.

---

*This project structure integrates universally with modern Anthropic AI Coding standard practices (SKILL.md). Check the bundled SKILL.md file for the specialized execution patterns used by internal autonomous IDE agents.*
262 changes: 262 additions & 0 deletions skills/hubspot-leadgenius/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
---
name: hubspot-leadgenius
description: Use this skill whenever the user asks to import, sync, migrate, or export leads from LeadGenius into HubSpot. This is the definitive guide and toolset for LeadGenius to HubSpot integration. Covers Private App setup, schema creation, rate-limit bypassing (using X-Admin-Key), JSON parsing for AI scores/emails/company descriptions, and batch upserts using the HubSpot v3 APIs.
---

# LeadGenius → HubSpot Import API Pipeline

> How to fully automate the extraction of enriched leads from LeadGenius and synchronize them natively into a HubSpot portal, with dynamic property group creation and exhaustive AI insight payload parsing.

---

## Table of Contents

0. [Overview](#0-overview)
1. [Prerequisites](#1-prerequisites)
2. [Creating the HubSpot Private App](#2-creating-the-hubspot-private-app)
3. [LeadGenius API Configuration & Bypass](#3-leadgenius-api-configuration--bypass)
4. [LeadGenius JSON Field Reference](#4-leadgenius-json-field-reference)
5. [Creating Custom Properties inside HubSpot](#5-creating-custom-properties-inside-hubspot)
6. [Importing Contacts & Data Mapping](#6-importing-contacts--data-mapping)
7. [Creating Saved Views (For SDRs)](#7-creating-saved-views-for-sdrs)
8. [Complete Automated Execution](#8-complete-automated-execution)
9. [Troubleshooting](#9-troubleshooting)

---

## 0. Overview

### What This Does

```text
LeadGenius Automation API → HubSpot Contacts Database
Over 120 nested objects Native Custom CRM Properties
Full X-Admin-Key Bypass Property Group (LeadGenius AI)
```

### Architecture

The LeadGenius API structure is highly complex, often burying core intel like Company Descriptions and direct phone arrays inside concatenated pipe-separated `:Mobile: | :Direct:` strings or JSON-wrapped string layers (`{"subject": "...", "content": "..."}`).

This guide bridges the gap structurally by:
1. **Dynamic Authentication:** Using `X-Admin-Key` arrays to completely override LeadGenius standard API throttling bottlenecks.
2. **Schema Standardization:** Emitting native HTTP POST requests to create a localized `leadgenius_data` Property Group on HubSpot immediately upon bootstrap.
3. **Deep Extraction:** Natively unpacking AI analysis, recommendation texts, and formatting integer matrices without UI friction.
4. **Massive Deduplication:** Launching 100-batch recursive endpoints routing via HubSpot's High-Level Upsert endpoints triggering on standard `email` objects.

### API Strategy Summary

| Operation | API Used | Why |
|-----------|----------|-----|
| HubSpot Authentication | Private App Token (Bearer) | Immediate API routing with no OAuth authorization hassle. |
| LeadGenius Fast Extraction | `X-Admin-Key` Headers | Overrides the typical API rate limits (HTTP 429) natively. |
| Create Property Group | `crm/v3/properties/groups` | Ensures all AI parameters don't clutter the global CRM view. |
| Create Properties | `crm/v3/properties/contacts`| Establishes schema integrity instantly without manual input. |
| Insert/Update Leads | `crm/v3/objects/contacts/batch/upsert`| Standard CRUD handling utilizing `idProperty: email`. |
| Create List Views | ❌ Manual Process | HubSpot restricts visual dashboard component programmatic builds. |

---

## 1. Prerequisites

### Software Requirements

```bash
pip3 install requests python-dotenv
```

### Environment Configuration

Create a local `.env` file at the root of your execution directory securely:

```env
# LeadGenius
LGP_API_KEY=your_standard_lg_token
LGP_MASTER_KEY=your_admin_bypass_token

# HubSpot
HUBSPOT_API_KEY=your_private_app_bearer_token
```

---

## 2. Creating the HubSpot Private App

In order to seamlessly authorize interactions with your Hubspot infrastructure, you must secure a native Private App token.

1. Click the **⚙️ Settings** icon in your HubSpot main navigation bar.
2. In the left sidebar, route to **Integrations > Private Apps**.
3. Click **Create private app**.
4. Basic Info: Name your deployment `LeadGenius Sync`.
5. Under the **Scopes** tab, explicitly inject these functional read/write headers:
- `crm.objects.contacts.read`
- `crm.objects.contacts.write`
- `crm.schemas.contacts.read`
- `crm.schemas.contacts.write`
6. Click **Create app** and securely port your new Access Token directly to `HUBSPOT_API_KEY` in your `.env`.

---

## 3. LeadGenius API Configuration & Bypass

Standard integrations fail aggressively on large environments because LeadGenius throttles basic API tokens recursively. We invoke native administrative clearance bypassing this framework utilizing `X-Admin-Key`.

When querying the core lead engine, we establish dual headers natively:
```python
LG_HEADERS = {
'X-API-Key': os.getenv('LGP_API_KEY'),
'X-Admin-Key': os.getenv('LGP_MASTER_KEY')
}
import requests
r = requests.get("https://api.leadgenius.app/api/automation/leads", headers=LG_HEADERS)
```

> [!CAUTION]
> When `X-Admin-Key` is utilized natively, the LeadGenius API structurally shifts the standard JSON payload directly inside an isolated `data` dictionary layer. Any scripts targeting `.get('id')` will fatally fail unless structurally targeting `.get('data', {}).get('id')`.

---

## 4. LeadGenius JSON Field Reference

LeadGenius exports deep multi-layered JSON metadata. We meticulously map these dynamically into HubSpot.

### Standard Field Mapping (Base Infrastructure)

| LeadGenius Object Column | HubSpot Internal ID | Execution Action |
|-------------------------|---------------------|------------------|
| `firstName` | `firstname` | |
| `lastName` | `lastname` | Maps to "Unknown" if natively null. |
| `title` | `jobtitle` | |
| `companyName` | `company` | |
| `email` | `email` | Serves as the primary ID key for Batch Upsert arrays. |

### Complex AI Extraction Fields (Custom Framework)

| LeadGenius Nested Object | HubSpot Internal Structure | Python Filter Strategy |
|--------------------------|----------------------------|------------------------|
| `aiLeadScore.ai_score` | `lg_ai_score` | Parsed securely via `int(float(val))` removing decimal vectors natively. |
| `capture_all > :Company Description:` | `lg_company_description` | Regex mapped natively overriding limited `companyValueProp` matrices. |
| `phoneNumber` / `sanitizedPhoneNumber` | `mobilephone` | Resolves uniquely against HQ endpoints strictly using standard direct routes. |
| `ai1` / `aiColdEmail` | `lg_cold_email` | Structurally stringified clearing heavily fragmented `{"subject"}` objects and `<br>` elements natively. |
| `aiScoreJustification` | `lg_justification` | Safely encoded utilizing multi-line parameters stripping `\n` carriage limits. |
| `aiScoreRecommendation` | `lg_recommendation` | Text-area extraction. |

### Enrichment Target References

| Target Endpoint | HubSpot Structural Map | Type Format |
|-----------------|------------------------|-------------|
| `linkedinUrl` | `lg_linkedin_url` | URL Block |
| `companyLinkedinUrl` | `lg_company_linkedin` | URL Block |
| `seniority` | `lg_seniority` | Text Format |

---

## 5. Creating Custom Properties inside HubSpot

All integrated properties must systematically map to `lg_` prefixed tables under a master `leadgenius_data` component.

### Example Schema Execution Array

The following snippet natively configures standard extraction components automatically:

```python
import requests, os
from dotenv import load_dotenv

load_dotenv()
HS_HEADERS = {
'Authorization': f"Bearer {os.getenv('HUBSPOT_API_KEY')}",
'Content-Type': 'application/json'
}

def setup_properties():
# 1. Establish Property Group
group_req = requests.post(
'https://api.hubapi.com/crm/v3/properties/contacts/groups',
headers=HS_HEADERS,
json={"name": "leadgenius_data", "displayOrder": -1, "label": "LeadGenius AI Data"}
)

# 2. Extract and Post Objects
properties = [
{"name": "lg_ai_score", "label": "LG AI Score", "type": "number", "fieldType": "number", "groupName": "leadgenius_data"},
{"name": "lg_company_description", "label": "LG Company Description", "type": "string", "fieldType": "textarea", "groupName": "leadgenius_data"},
# Added extra...
]

for prop in properties:
requests.post('https://api.hubapi.com/crm/v3/properties/contacts', headers=HS_HEADERS, json=prop)
```

---

## 6. Importing Contacts & Data Mapping

Once schema arrays are structurally localized on HubSpot, you bypass the standard REST API limits using High-Volume Endpoints (`batch/upsert`).

```python
def build_hs_contact(lead):
# Parses unique JSON strings
def parse_email_json(text):
if not text: return ""
try:
import json
parsed = json.loads(text)
return f"Subject: {parsed.get('subject', '')}\n\n{parsed.get('content', '')}".replace('<br>', '\n')
except: return str(text).replace('<br>', '\n')

props = {
"email": lead.get('email'),
"firstname": lead.get('firstName'),
"lg_ai_score": str(int(float(lead.get('aiLeadScore', {}).get('ai_score', 0)))),
"lg_company_description": lead.get('capture_all_parsed', {}).get('Company Description')
}
return {k: v for k, v in props.items() if v}

# Batch Upsert Loop
chunk = leads[0:100]
inputs = [{"idProperty": "email", "id": c['email'], "properties": c} for c in chunk if c.get('email')]

response = requests.post(
'https://api.hubapi.com/crm/v3/objects/contacts/batch/upsert',
headers=HS_HEADERS,
json={"inputs": inputs}
)
```

---

## 7. Creating Saved Views (For SDRs)

UI Saved Layouts cannot be programmatically initiated via Standard Endpoints securely. Administrators must instruct internal teams utilizing the following manual pipeline layout configurations:

1. Launch HubSpot and access the **Contacts Data Table**.
2. Navigate directly to **Add View > Create New View** and define `SDR LeadGenius Outbound`.
3. Select **Edit Columns** and firmly integrate:
- `Lead Status`
- `LG AI Score`
- `LG Recommendation`
- `Mobile Phone`
4. Make sure your SDR operators utilize **Settings > Objects > Contacts > Record Customization** natively to permanently anchor the `leadgenius_data` sidebar at the apex of user visual fields on the Contact Card.

---

## 8. Complete Automated Execution

The unified deployment matrix script integrating Schema Build, Extraction Arrays, Bypass Authentication, JSON Sanitization string manipulation, and Batch Array POSTing natively is available securely within the executed script pipeline.

Simply run recursively:
```bash
python3 scripts/lg_full_to_hs.py
```

---

## 9. Troubleshooting

| Error Code/Symptom | Direct Internal Cause | Execution Fix |
|--------------------|-----------------------|---------------|
| `PROPERTY_DOESNT_EXIST` | Script failed to setup custom Schema. | Wipe memory cache and rerun step 1 property validation. |
| `KeyError: 'data'` | The LeadGenius script failed to use `X-Admin-Key` properly. | Verify the `LGP_MASTER_KEY` is fully established in standard `.env`. |
| Zero Properties Imported | The Batch API failed matching standard fields. | Ensure array targets the CRM Endpoint Native Field Identifier mapping (`email`). |
| `HTTP 429` | Reverted to Standard LeadGenius Limits. | Confirm bypass admin keys are pushed exactly as `X-Admin-Key`. |
Loading