This project automates the process of generating an AI-powered research report for new HubSpot leads and attaching a link to that report back onto the HubSpot contact record. It uses Val Town as the serverless backend, HubSpot webhooks and APIs, and Perplexity AI for generating the research.
- Automated Lead Research: When a new contact (lead) is created in HubSpot, a research report is automatically triggered.
- Perplexity AI Integration: Leverages Perplexity AI to generate insightful reports about the lead, their potential company, relevant industry trends, and tailored use cases for a specified product (e.g., PixieBrix).
- HubSpot Integration:
- Receives new contact notifications via HubSpot Webhooks.
- Fetches detailed contact information using the HubSpot API.
- Updates the contact record with a link to the generated research report.
- Serverless & Easy to Deploy: Runs on Val Town, requiring minimal setup.
- Dynamic Report Serving: The same Val Town val that processes webhooks also serves the stored research reports via a unique URL.
- Intelligent Prompting: Attempts to identify the lead's actual company, especially when generic email domains (like gmail.com) are used.
- A Val Town account.
- A HubSpot account with administrative privileges to:
- Create Private Apps.
- Manage CRM properties.
- Set up Webhooks.
- A Perplexity AI account and an API key.
- In your HubSpot account, navigate to Settings (gear icon) > Integrations > Private Apps.
- Click "Create private app".
- Basic Info:
- Name: Give your app a descriptive name (e.g., "ValTown Lead Research").
- Description: (Optional) Briefly describe its purpose.
- Scopes: Go to the "Scopes" tab. You need to grant the following permissions:
crm.objects.contacts.read
- To read newly created contact details.crm.objects.contacts.write
- To update the contact with the report link.- (Recommended for robustness)
crm.schemas.contacts.read
- (Recommended for robustness)
crm.schemas.contacts.write
- Click "Create app".
- After creation, HubSpot will show you an Access Token. Copy this token securely. This will be your
HUBSPOT_API_KEY
in Val Town.
- In HubSpot, navigate to Settings (gear icon) > Properties (under "Data Management").
- Ensure "Contacts" is selected as the object.
- Click "Create property".
- Property Details:
- Object type: Contact
- Group: Contact information (or any group you prefer)
- Property label:
Research Report URL
(or similar) - Click "Next".
- Field type: Select "Single-line text".
- Click "Create".
- Note down the Internal name of this property (e.g.,
research_report_url
). The Val Town script usesresearch_report_url
by default. If yours is different, you'll need to update the script.
- Navigate back to your Private App settings in HubSpot (Settings > Integrations > Private Apps > Your App Name).
- Go to the "Webhooks" tab.
- Click "Create subscription".
- Target URL: This will be the URL of your Val Town val.
- If you plan to use a custom subdomain for your Val Town val (e.g.,
https://your-app-name.val.run
), enter that. - Otherwise, it will be in the format
https://YOUR_VALTOWN_USERNAME-VAL_NAME.web.val.run
. You might need to create the val first (see Step 2) to get this exact URL.
- If you plan to use a custom subdomain for your Val Town val (e.g.,
- Object type: Select "Contact".
- Event type: Choose "Contact created" (often listed as
contact.creation
). - Save the webhook subscription.
- Go to your Val Town workspace.
- Create a new HTTP val. Name it descriptively, e.g.,
hubspotLeadWebhook
.- The code uses JSX, so ensure the file extension is
.tsx
if you're using the Val Town CLI, or just paste the code into the browser editor. The provided code includes/** @jsxImportSource https://esm.sh/react@18.2.0 */
at the top.
- The code uses JSX, so ensure the file extension is
- Copy the entire code from
hubspotLeadWebhook.http.ts
(as provided in this project) and paste it into your new val.
In your Val Town val's settings, you need to set the following environment variables:
HUBSPOT_API_KEY
: Paste the Access Token you copied from your HubSpot Private App.PERPLEXITY_API_KEY
: Paste your API key from Perplexity AI.
If you didn't set a custom subdomain for your val, its URL will be something like https://YOUR_USERNAME-hubspotLeadWebhook.web.val.run
. Ensure this exact URL (or your custom subdomain URL) is used in the "Target URL" field of your HubSpot webhook subscription (Step 1c).
The script uses research_report_url
as the internal name for the HubSpot custom property:
const hubspotPropertyInternalName = "research_report_url";
If the internal name of the property you created in HubSpot (Step 1b) is different, update this line in the Val Town script accordingly.
- Webhook Trigger: When a new contact is created in HubSpot, it triggers the configured webhook, sending a
POST
request to your Val Town val. - Contact Fetch: The Val Town script receives the webhook, extracts the contact ID, and uses the HubSpot SDK to fetch the full details of the new contact.
- Company Identification: It attempts to derive a company name from the contact's email address and identifies if the domain is generic (e.g., gmail.com).
- Perplexity AI Prompting:
- A detailed prompt is constructed for Perplexity AI.
- If a generic email domain is detected, the prompt explicitly instructs Perplexity to research the individual's actual company rather than the email provider.
- The prompt asks for:
- The individual's professional profile and primary company/project.
- An overview of that primary company/project.
- Recent news and trends relevant to the individual or their company.
- Tailored use cases for PixieBrix (this can be customized to your product) relevant to the individual and their specific company context.
- Report Generation: The script calls the Perplexity AI API (
sonar
model by default) to generate the research report. - Blob Storage: The generated report text is stored in Val Town's
std/blob
storage with a unique key (e.g.,research_reports/contact_{CONTACT_ID}_{TIMESTAMP}.txt
). - HubSpot Update: The script constructs a URL pointing back to itself (using its own hostname and the blob key as a query parameter, e.g.,
https://your-val-url.val.run/?key=BLOB_KEY
). This URL is then saved to the custom "Research Report URL" field on the HubSpot contact record. - Report Serving: When the generated URL is accessed (e.g., by clicking the link in HubSpot), the same Val Town val handles the
GET
request. It retrieves the report text from blob storage using the provided key and serves it as plain text.
- Ensure all HubSpot configurations (Private App scopes, custom property, webhook) are correctly set up and saved.
- Ensure your Val Town val (
hubspotLeadWebhook.http.ts
) is saved and your environment variables (HUBSPOT_API_KEY
,PERPLEXITY_API_KEY
) are correctly set. - In HubSpot, create a new test contact with an email address.
- Test with a generic email (e.g., a @gmail.com address for a known professional like "Steve Krouse").
- Test with a company-specific email if possible.
- Check Val Town Logs: Open the logs for your
hubspotLeadWebhook
val in Val Town. You should see:- "Received HubSpot webhook payload..."
- "Fetched HubSpot Contact Details (SDK)..."
- "Generating Perplexity research report for..."
- "Research report text received from Perplexity: ..." (This should show the actual report text).
- "Updating HubSpot contact ... with report link: ..."
- "HubSpot contact ... updated successfully."
- If there are errors from HubSpot or Perplexity, they will be logged here.
- Check HubSpot Contact:
- Open the newly created contact record in HubSpot.
- Find your custom property (e.g., "Research Report URL"). It should contain a link like
https://your-val-url.val.run/?key=...
.
- Verify Report Link:
- Click the link in the HubSpot custom property.
- Your browser should open a new tab displaying the plain text research report generated by Perplexity.
- Check the Val Town logs again; you should see entries related to the
GET
request for serving the blob, including "Raw object from blob.get()..." and "Successfully extracted text from blob...".
- Perplexity Model: You can change the Perplexity AI model used (default is
"sonar"
) in theperplexityPayload
section of the script. Refer to Perplexity AI documentation for available models. - Prompts: The
perplexitySystemPrompt
andperplexityUserPrompt
can be extensively customized to change the focus, tone, or content of the research report. - Generic Domains: The
genericDomains
array in the script can be updated if you want to add or remove email domains that should trigger the special "search for actual company" logic. - PixieBrix Use Cases: Modify the prompt to ask for use cases relevant to your product or service.
- "Enterprise Lead" Criteria: The script includes a
TODO
comment for adding logic to identify "Enterprise Leads" if you want to trigger research only for specific types of leads.
This README should provide a good starting point!