Welcome to my project for simplifying leads management in Notion!
I work at a B2B company, where I support the sales team by collecting leads, crafting tailored emails, and tracking follow-ups to book meetings. While Notion serves as our primary tool for managing these workflows, handling large datasets often feels cumbersome and slow.
To address these challenges, I developed a Python-based solution designed to simplify and accelerate my workflow. This program streamlines the management of leads — emails of professionals working in companies that match our target group — and makes the process of handling leads smoother, more efficient, and far less repetitive.
With this tool, I’ve saved significant time, reduced frustration, and transformed a clunky process into a seamless and productive experience.
I work at a B2B company, supporting the sales team by managing email outreach to leads. My role includes responsibilities like social media, website management, and marketing, which naturally brings in a steady stream of leads. My primary tasks involve collecting these leads (email addresses) from various channels, following up with tailored emails based on pre-defined templates, and tracking progress.
I rely on Notion to manage this workflow, including tracking which leads have been contacted, what email templates were sent, responses received, follow-up reminders, and the dates of contact. The ultimate goal is to convert leads into booked meetings with the sales team.
While Notion is an excellent tool that I use extensively for many tasks, I’ve found it somewhat cumbersome and inefficient for managing this specific process. Despite its limitations, I chose Notion to centralize all my data, but I’m fully aware it’s not the ideal platform for email workflow management.
With this Python project, my goal is to build a tool that simplifies, automates, and enhances this workflow, saving me time and effort while addressing Notion’s limitations for email management.
I have two main workflows in Notion; collecting leads, and managing leads. I designed my Python program to align seamlessly with these workflows, optimizing the processes I already have in place and rely on daily. By building on my existing structure, the program enhances efficiency without disrupting familiar routines.
These workflows are described in more detail below.
I typically start my workday by spending around 30 minutes gathering email addresses from channels where potential leads can be found, such as social media, our CRM system, the company website, or other platforms frequented by our target audience. These email addresses are then added to a list of potential leads to be contacted.
- Find email that I find relevant to contact.
- Check if email is in database already.
- Add email to database if email isn't already there.
- Add information about company and notes (if any)
When a Notion database becomes very full, I’ve noticed it tends to become sluggish and laggy, making data handling unnecessarily time-consuming. This is especially challenging in my case, where I need to view the entire database, which contains hundreds of data points. Beyond the performance issues, however, there is a significant limitation in Notion’s functionality: the lack of automatic duplicate detection for databases.
This shortcoming requires me to manually ensure that an email doesn’t already exist in the database before adding it. To do so, I must load all database rows — clicking "load more" repeatedly — and then manually search (Ctrl + F) for every email I want to add. Additionally, I need to verify that the company associated with the email is not already in our sales list. This involves switching to a separate database, loading its data in a similar manner, and manually searching for the company name. These extra steps, while manageable in isolation, become highly repetitive and time-consuming when performed daily.
Despite my diligence in double-checking, duplicates occasionally slip through — whether it’s the same email added twice or contacting a lead from a company that’s already in our sales list. This has resulted in scenarios where emails were sent redundantly, even to leads who had previously declined. An automated solution for detecting duplicates across both databases would save significant time, reduce errors, and streamline the entire workflow.
In my leads database, I keep track of each lead’s status and the dates of contact. When I send an email, I update the status to something like "E-mail 1," showing that the lead received an email using that template. I use several templates in my workflow. If a lead replies and we start a conversation, I change their status to something like "Meeting Booked" or "Not Interested" and note the date of the update.
If a lead doesn’t respond within a week, I send a reminder email, updating their status to something like "Reminder E-mail 1" and recording the date it was sent. I also update notes in the database regularly, adding details such as if a lead wants to be contacted later or has shown interest in a specific product. This helps me stay on top of all interactions.
My workflow isn’t fixed but adapts based on when I send emails or receive responses. As soon as a lead replies, I update the database immediately to ensure the information is always accurate. Since my sales team depends on this database, keeping it up-to-date is essential.
When I send an email to a lead, or receive a reply from a lead, I have to open the database, repeatedly click "load more" to access all the rows, and wait for everything to load — a process that becomes slow with larger datasets.
Once the database is fully loaded, I use Ctrl+F to search for the specific email and update the information. While this process is relatively straightforward, repeating it multiple times a day quickly becomes tedious. Constantly reopening the database, waiting for it to load, and searching for emails disrupts the workflow and makes the process feel unnecessarily time-consuming.
Of course, keeping the database open all the time would help streamline this process. However, since I use Notion extensively for various tasks, I often navigate elsewhere and forget to keep the leads database ready, adding another layer of inefficiency to my daily workflow.
I have two databases in Notion, one for emails to potential new leads and one for current customers.
This is a list of email addresses. While the emails here are fictional, they accurately represent the structure of my real leads database. This is where I gather all the leads I identify and track their status, notes, and other relevant details. The database consists of five columns, which are described below.
| Column | Description |
|---|---|
| The email address of the potential lead. | |
| Company | The company where the lead works. This is important for our B2B operations as we check it against the company sales list database. More details provided below. |
| Status | Tracks the lead's status, such as whether an email has been sent, if they’ve responded, or if a meeting has been booked. Additional details are outlined below. |
| Latest Contact | Records the date of the most recent interaction with the lead. This is key for scheduling reminder emails to leads who haven’t replied. |
| Notes | A space to log additional information about the lead, such as specific preferences or follow-up actions. |
The status column has specific options to choose from. The status can only be one of the following statuses:
This database showcases all the companies we are already selling to. These are businesses where our Key Account Managers are actively engaged in conversations or ongoing sales. As such, I don’t need to include these companies in my lead management process, ensuring my focus remains on new opportunities.
This database is intentionally simple, containing only the companies that are our current customers. As a B2B company, we focus on tracking companies rather than individual contacts within them. The primary purpose of this database is to ensure that leads in the email list are not already existing customers.
There have been discussions about complementing this database with additional information, such as contact persons and which salesperson is responsible for the account. However, this information serves no purpose for me in my role. My primary concern is determining whether a company is already in our sales list, ensuring I don’t contact individuals at companies we are already selling to. This database is critical for preventing overlap between leads and existing customers, ensuring our email outreach is efficient and focused.
This list isn’t updated frequently, and when updates are needed, I can handle them manually. For now, I’ve chosen not to include this database in the Python program, besides checking for company overlaps, as there are other areas where Python automation provides far greater efficiency and impact.
Now that we've outlined the databases, workflows, and current issues with the workflow, let's focus on what we aim to achieve with this project. The goal is to streamline and simplify the process of managing leads while addressing the inefficiencies and limitations of the current system. This tool should enable a quick and seamless workflow, allowing for efficient handling of leads without unnecessary complexity or delays.
Below is an overview of the primary goals for the project:
| Goal | Description |
|---|---|
| Add New Leads | Provide a quick and easy way to add new email leads to the database with minimal effort. |
| Automatic Duplicate Checker | Ensure no duplicate emails are added by automatically checking if the email already exists. |
| Company Sales List Checker | Automatically check if the lead belongs to a company we already sell to, avoiding redundant outreach. |
| Update Email Status | Simplify the process of updating the status and contact date of an email lead. |
| Update Notes | Make it easy to update or add notes for existing leads to keep track of relevant details. |
| Minimal Options and Text | Keep the workflow simple and to the point, avoiding unnecessary text or options for a fast UX. |
| Clear Feedback | Provide immediate and clear feedback to instantly confirm whether the expected action was successful or if an issue, like a duplicate, occurred. |
The overarching goal is to create a tool that integrates seamlessly into the current workflow, saving time and effort while providing the necessary features to manage leads effectively. This project aims to prioritize simplicity, speed, and usability for daily tasks.
This requirements list outlines the specific functionality and features that this program must deliver to meet the project goals. Each requirement has been tailored to address the challenges described in the project's background and workflow, focusing on simplicity, speed, and accuracy. This list of requirements serves as the foundation for the program's development.
| Requirement | Description |
|---|---|
| Notion API Integration | Use the Notion API to interact with two separate databases (leads and company sales list). This includes searching, retrieving, adding, and updating data efficiently. |
| Add New Leads | The program must allow the user to input a new email address, company name, and optional notes, and add these to the leads database. |
| Duplicate Email Check | Before adding a new email, the program must automatically search the leads database for the email. If the email is there, don't add the email to leads database. |
| Block Invalid Emails | Validate email addresses using a predefined format and reject invalid entries with a clear error message. |
| Handle Optional Company Input | Allow the user to optionally input a company name when adding a new lead, and verify against the company sales list database if provided. |
| Company Sales List Check | The program must automatically search the company sales list database to check if the lead’s company is already a customer. If it is, don't add the email to leads database. |
| Update Lead Status | The program must allow users to update the status field of a lead with predefined options. |
| Update Notes | The program must provide an option to either add to or completely replace the notes field for an existing lead. |
| Immediate Feedback | After every action, the program must display a message confirming success or failure. |
| Error Handling for Inputs | If the user inputs an invalid email, status, or note action, the program must display a clear error message and prompt the user to retry. |
| Date Auto-Update | When updating a lead's status, the program must automatically update the "Latest Contact" field with the current date. |
| Efficient Database Loading | The program must bypass Notion’s "load more" limitation by directly querying the full database via the API. |
| Seamless Database Switching | If a company check is required, the program must automatically switch to the company sales list database and return to the leads database afterward. |
| Predefined Status Options | The program must restrict status updates to a fixed set of options (e.g., "Not Sent," "E-mail 1," "Meeting Booked") to maintain data consistency. |
This flowchart, created in Adobe XD, illustrates the basic process for adding or updating leads in the program. The focus is on minimizing steps and creating an efficient, user-friendly flow. Using a flowchart as a visual representation allows me to clearly see the logical flow of the program, helping me break down workflows into manageable steps.
| Shape/Color | Meaning |
|---|---|
| Circle | Represents the start or end of the flow. |
| Diamond | Represents a decision point in the workflow, such as yes/no or multiple choices. |
| Rectangle | Represents an input or print step. |
| Purple | Represents a program action, such as checking the database or displaying a message. |
| Grey | Represents a user action, such as entering an email or selecting a status. |
| Feature | Description |
|---|---|
| Seamless Workflow | The program is designed to loop in a way that aligns with my workflow. For example, if I try to add an email that already exists in the leads database, I want the program to prompt me to re-enter a new email instead of sending me back to the start. This ensures continuity in the "add leads" process. |
| Updating Lead Workflow | In my daily workflow, updating a lead's status is far more common than updating notes. When notes are added, it’s usually in conjunction with a status update. It’s very rare that I update notes independently. This program reflects that workflow, prompting the user to add notes immediately after updating a lead’s status. |
| Error Handling | Similarly, if I for example add an email associated with a company already in the sales list or attempt to update a lead that doesn’t exist in the database, I want clear error messages and the ability to quickly retry without disrupting the workflow. |
| No Hard Stops | The program is intentionally designed to never "stop" or "end". Once I successfully complete an action — such as adding a new lead or updating a lead’s information — the program should seamlessly return to the beginning, ready for the next input. |
| No Delete Option | Deleting leads from the database is extremely rare in our workflow. We maintain records of all interactions, including those who are not interested, to ensure a complete history. If someone requests not to be contacted, their status is updated to "Not Interested," and they are excluded from further communications. The only scenario where an email is deleted is upon request, typically for GDPR compliance. Since this situation has never occurred, handling such cases manually is sufficient for now. |
This program was built to simplify and streamline the workflow of managing leads in Notion. Below are the key features that have been implemented, highlighting what the program can do and how it aligns with the initial requirements and flowchart. Any deviations or additions have been noted.
| Feature | Description |
|---|---|
| Adding New Leads | 1. Easily add new leads to the leads database with minimal input required. 2. Includes optional fields for company name and notes. 3. Automatically set status "Not sent" and leave date field empty. |
| Automatic Leads Duplicate Check | 1. Automatically checks for duplicate emails in the leads database when adding new leads. 2. Prevents duplicates from being added. 3. Shows clear error messages if duplicates are detected. 4. Displays success messages for non-duplicates. |
| Automatic Company Sales List Check | 1. Verifies whether a company associated with a lead already exists in the sales list database. 2. Prevents leads from being added if their company is an existing customer. 3. Shows clear error messages if a company is already in the sales list. 4. Displays success messages when the company is not in the sales list. |
| Update Status for Existing Leads | 1. Allows users to update the status of a lead (e.g., "E-mail 1," "Meeting") based on predefined options. 2. Displays the current status before updating. 3. Shows possible statuses to choose from. 4. Allows users to immediately update notes after status updates to fit the normal workflow. |
| Date Auto-Update | 1. Automatically updates the "Latest Contact" field whenever a lead's status changes. 2. Uses the current date dynamically for updates. |
| Update Notes for Existing Leads | 1. Enables users to add or replace notes for existing leads. 2. Displays current notes before input for clarity. |
| Clear and Immediate Feedback | 1. Provides clear, concise feedback for all actions, such as successful updates, errors, or duplicate detections. 2. Ensures users always know whether the intended action was successful or requires adjustments. |
| Minimal User Interaction | 1. Designed to minimize inputs and steps, aligning with the quick workflow needed for sales management. 2. Loops processes to allow users to fix errors without restarting the workflow. |
| Enhanced User Experience | 1. Uses color-coded feedback (via Colorama, more information below) in a bold font to highlight program information. 2. Error messages and success confirmations are designed to provide all necessary information without overwhelming the user. 3. Emojis enhance feedback, making it easier to recognize successes or issues. |
| Colored Messages | 1. Differentiates program output from user input by using cyan for program messages and white for user input. 2. Error messages are displayed in red for immediate attention. 3. Success messages are displayed in green to confirm successful actions. |
| Input Error Handeling | 1. Prevents invalid inputs, such as missing "@" in email addresses. 2. Prompts users to try again if an input is invalid. 3. Skips unnecessary inputs without generating errors. |
| Avioding Breaks | 1. Ensures the program never stops abruptly or loops back to the beginning when errors happen. |
✅ More Feedback Messages
Additional confirmation and error messages were added to enhance user clarity.
✅ Improved Error Handling
The program ensures smooth loops when invalid inputs occur, rather than requiring users to start over.
✅ Focus on UX
The color-coded system and reduced steps were optimized beyond the initial requirements to ensure the program feels intuitive and fast.
✅ Enhanced Input Validation
The program ensures that user inputs are accurate by verifying key details, such as confirming that an email address is valid and that the status selected matches predefined options. This prevents incorrect or invalid data from being added to the database, maintaining its integrity and reliability.
✅ Optional to add Company
Due to my workflow, I chose to have company as an optional input when adding new leads. I don't always have information about the company where the potential lead works.
✅ Skip Functionality
While developing this program, I quickly realized the need for a way to exit loops gracefully, especially when a user selects something incorrect. To address this, I implemented a "skip" function, allowing the user to simply type skip in any input field to return to the start of the program seamlessly.
This program is deployed via Heroku and can be accessed here: Auto Emails Application
To view the leads database and verify that leads are being added or updated, visit: Leads Database
To access the company sales list database and ensure accuracy in the workflow, visit: Company Database
Adding a lead to the database is a straightforward process with minimal steps, designed for efficiency. Below is a step-by-step guide on how to add a lead:
- Start the program
Launch the program with Heroku app here: Auto Emails Application - Choose "Add"
When askedDo you want to add or update email? (add/update):typeaddand press enter. - Enter Email
Type the email you want to add. If it already exists in the database, you’ll see a red message and can re-enter a new email. If it’s new to the database, you’ll see a green confirmation. - Enter Company (Optional)
Add the company name or press enter to skip. If the company is in the sales list database, you’ll be asked to try again with a different email. Otherwise, you’ll get a green confirmation. - Add Notes (Optional)
Add any relevant notes or press enter to leave it blank. - Done!
A green success message confirms the lead was added. You can verify this here: Leads Database
Updating a lead provides more options compared to adding a lead since you might only want to update the status, the notes, or both. Here’s a step-by-step guide to updating a lead:
- Start the program
Launch the program with Heroku app here: Auto Emails Application - Choose "Update"
When askedDo you want to add or update email? (add/update):typeupdateand press enter. - Enter Email
Type the email you want to add. If the email is found in the database, you'll proceed to the next step. If the email is not found, you'll receive an error message and be asked to re-enter an email. - Choose what to update
You'll be asked:Do you want to update status or notes? (status/notes):. Typestatusto update the lead's status. Typenotesto update the lead's notes directly. - Update the status (if applicable)
If you choose to update the status, the program will display the current status and valid options (e.g.,Not sentE-mail 1Meeting). Enter the new status from the list of valid options. The program will automatically update the status and set the latest contact date to the current date. - Choose to update notes after status update (if applicable)
After updating the status, the program will askDo you want to add or update notes as well? (yes/no):. Typeyesto proceed with updating the notes. Typenoif you don’t want to update the notes. - Update the notes (if applicable)
If you choose to update the notes, the program will show the current notes. You'll be askedWhat do you want to do with the notes? (add/replace):. Typeaddto add new notes to the existing ones. Typereplaceto overwrite the current notes. Enter the new note content when prompted. - Done!
A green success message confirms the lead was updated. You can verify this here: Leads Database
The program is designed to prioritize speed, clarity, and precision for both adding and updating leads. The following features ensure a smooth and efficient workflow:
Colorama is an integral part of this program, enhancing the user experience with color-coded feedback in the terminal. It helps users quickly identify messages by their type, ensuring clarity and reducing confusion during interactions. In addition to colors, I use emojis to emphasize the success or failure of actions, making feedback both functional and visually intuitive.
| Color | Description |
|---|---|
| Cyan | Used for all program prompts to differentiate them from user inputs, this ensures the program’s messages are easily identifiable. |
| Green | Indicates successful actions, such as adding a lead to the database or confirming that a company is not in the sales list. |
| Red | Highlights errors or unexpected outcomes, such as duplicate emails or invalid inputs. |
🟢 Green Circle: Used in success messages to confirm that an expected action was completed, such as adding a new lead successfully.
🔴 Red Circle: Always paired with error messages to signify that an expected action did not occur.
Colorama was installed using the following command, as outlined in the official Colorama documentation:
pip install colorama
And import colors and styling to run.py with:
from colorama import Fore, Back, Style
I also ensured the Colorama library was included in the requirements.txt file, which was necessary for deploying the program on Heroku. This allows the program to run smoothly in the cloud environment.
The program is built around a Notion API integration, a Lead class for managing data, and a main function that serves as the entry point for user interaction. Below, I'll describe the key components of the program, highlight their functionality, and include code snippets for better understanding.
The program uses the Notion API to interact with two separate databases. I integrated it into my program by following the Notion Developers Get Started Guide and utilizing the Notion API library.
from notion_client import Client
Initialize Notion client
notion = Client(auth=creds["NOTION_TOKEN"])
And using the ID of the two databases:
# Database ID with lead emails
DATABASE_ID = "168284e4604f8013a728d0aa102775aa"
# Database ID for current customers company
COMPANY_DATABASE_ID = "168284e4604f80d7acfac51891eb0e3c"
The Notion token is stored in creds.json, which is hidden for privacy reasons.
The Lead class encapsulates the logic for managing leads. It interacts with the Notion API to perform CRUD (Create, Read, Update, Delete) operations.
Why use a class?
It keeps the code modular and reusable, and also encapsulates lead-specific logic (e.g., validation, database queries).
def create(self, email, company=None, notes=None):
"""
Add a new lead to the database.
"""
properties = {
"E-mail": {"title": [{"text": {"content": email}}]},
}
if company:
properties["Company"] = {
"rich_text": [{"text": {"content": company}}]
}
if notes:
properties["Notes"] = {
"rich_text": [{"text": {"content": notes}}]
}
self.notion.pages.create(
parent={"database_id": self.database_id}, properties=properties
)
print(
format_text(
f"🟢 Success! Lead '{email}' added to the database.",
color="green",
)
)
Initially, I structured my program using standalone functions to handle email validation, database queries, and updates. While this approach worked, it quickly became evident that managing multiple related functions was inefficient and repetitive. By switching to a class-based approach, I consolidated related functionality, improved code readability, and enhanced maintainability.
Below is an example of how I initially managed the functionality using separate functions:
def is_valid_email(email):
"""Check if email is valid."""
pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
return bool(re.match(pattern, email))
def find_email_in_database(email):
"""Check if email exists in the email database."""
response = notion.databases.query(database_id=database_id)
for page in response["results"]:
properties = page["properties"]
if properties["E-mail"]["title"][0]["text"]["content"] == email:
return page["id"]
return None
def add_email_to_database(email, company=None, notes=None):
"""Add email to database."""
properties = {
"E-mail": {"title": [{"text": {"content": email}}]},
}
if company:
properties["Company"] = {"rich_text": [{"text": {"content": company}}]}
if notes:
properties["Notes"] = {"rich_text": [{"text": {"content": notes}}]}
notion.pages.create(
parent={"database_id": database_id},
properties=properties,
)
print(f"🟢 Success! '{email}' has been added to the database.")
While functional, this approach caused repetitive code, making it harder to maintain or scale as new features were added.
By introducing a Lead class, I encapsulated all lead-related operations into a single structure, improving organization and reducing redundancy.
Code example from Lead class:
def __init__(self, notion_client, database_id, company_database_id):
"""
Set the Lead Class with Notion client and database IDs
"""
self.notion = notion_client
self.database_id = database_id
self.company_database_id = company_database_id
def is_valid_email(self, email):
"""
Validate the format of an email address.
"""
pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
return bool(re.match(pattern, email))
def find_by_email(self, email):
"""
Search for a lead in the email database by their email.
"""
response = self.notion.databases.query(database_id=self.database_id)
for page in response["results"]:
email_property = page["properties"]["E-mail"]
email_title = email_property["title"][0]["text"]["content"].lower()
if email_title == email.lower():
return page # Return the full page object
return None
def is_company_in_sales_list(self, company):
"""
Search for company in the current company sales list.
"""
response = self.notion.databases.query(
database_id=self.company_database_id
)
for page in response["results"]:
company_property = page["properties"]["Company"]
company_title = company_property["title"][0]["text"]["content"]
if company_title.lower() == company.lower():
return True
return False
Switching to a class-based code not only simplified the structure but also ensured the program could be extended more easily in the future. For example, methods like find_by_email, is_company_in_sales_list, and update_notes are now part of the Lead class, providing a cohesive way to interact with leads.
The main() function handles the user interaction loop. It allows users to add leads (prompts for email, company, and optional notes) and update leads (lets users modify the status or notes of an existing lead).
Flow Example in main():
if action == "add":
# Check if email is in database
if lead_manager.find_by_email(email):
print(
format_text(
f"🔴 Email '{email}' already exists in "
"the database. Please enter a new email.",
color="red",
)
)
continue
print(
format_text(
"🟢 Good to go! "
f"'{email}' does not exist in the database.",
color="green",
)
)
To avoid repetition, a function format_text was created for formatting messages in the terminal. This ensures consistent color coding and bold styling.
Before:
print("\033[1m" + Fore.RED + "Error message" + Style.RESET_ALL + "\033[0m")
After:
print(format_text("Error message", color="red"))
During development, I encountered a few challenges:
| Issue | Description | Solution |
|---|---|---|
Calling main from Lead Methods |
In the current implementation, the main function is called directly within methods of the Lead class (e.g., update_notes and update_status_with_notes). While functional, this approach doesn't feel like the best solution. |
A better solution would be to separate the program flow logic from the Lead class. This issue has however not been fixed in this version of the program but is planned as a future improvement. Refactoring the code to separate class responsibilities from program flow will make the code cleaner. |
| Formatting Message Repetition | Initial implementation repeated formatting logic for every message. | Created the format_text function to simplify message styling. |
| Notion Select Type Issue | Notion uses two types of select fields, one "select" and one "status". The program was trying to update with the wrong type, causing an error. | Updated the code to use the "status" type for the Notion select field. |
| Repetitive Notes Code | The handling of notes appears in two places: one after updating the status and another when adding notes directly. This results in repetitive code. | A potential solution is to create a dedicated function or method for managing notes, which can be reused in both scenarios to improve maintainability and reduce redundancy. However, this has not yet been implemented in the current version of the program. |
-
Python
The main programming language used in this project. -
HTML, CSS, JavaScript
Provided from the Code Institute P3 Template.
-
json
Parses thecreds.jsonfile to extract Notion API credentials securely. -
notion_client
Facilitates interaction with the Notion API, enabling CRUD (Create, Read, Update, Delete) operations in Notion databases. Documentation: Notion SDK for Python. -
re
Validates email addresses to ensure data integrity and prevent invalid entries in the database. Documentation: re library. -
datetime
Tracks and records the date of the latest interaction with leads for accurate updates. Documentation: datetime. -
colorama
Enhances the terminal interface by adding color-coded feedback, making user interactions more intuitive. Documentation: colorama.
-
Gitpod
Used for writing and testing the Python code in an online IDE environment. -
GitHub
For version control and repository management throughout the development process. -
Heroku
Deployed the program to Heroku for easy online access and testing.
-
Notion
The core database platform integrated with the project, serving as the leads database and company sales list for email tracking and management. -
Python Interpreter
Used locally for testing the program before deployment to Heroku. -
Adobe XD
Utilized to design the project’s flowchart, visually representing the program's logic and workflows. -
ChatGPT
Assisted in debugging, troubleshooting, and explaining unexpected behavior. Also provided guidance on best practices and solutions for cleaner, more efficient, and maintainable code.
The code was validated using the CI Python Linter. Initially, a few lines were flagged for exceeding the recommended length, but these issues have since been resolved. The code now passes validation without any errors or warnings, meeting all style and formatting guidelines.
The code was run through a Python syntax checker with no errors.
To evaluate whether the program meets the goals and requirements outlined earlier, we conducted a thorough review of each feature. Below is a detailed checklist of the requirements, descriptions, and whether the program successfully implemented them.
| Requirement | Description | Implemented Successfully? |
|---|---|---|
| Notion API Integration | Use the Notion API to interact with two separate databases (leads and company sales list). This includes searching, retrieving, adding, and updating data efficiently. | ✅ Yes |
| Add New Leads | The program must allow the user to input a new email address, company name, and optional notes, and add these to the leads database. | ✅ Yes |
| Duplicate Email Check | Before adding a new email, the program must automatically search the leads database for the email. If the email is there, don't add the email to leads database. | ✅ Yes |
| Block Invalid Emails | Validate email addresses using a predefined format and reject invalid entries with a clear error message. | ✅ Yes |
| Handle Optional Company Input | Allow the user to optionally input a company name when adding a new lead, and verify against the company sales list database if provided. | ✅ Yes |
| Company Sales List Check | The program must automatically search the company sales list database to check if the lead’s company is already a customer. If it is, don't add the email to leads database. | ✅ Yes |
| Update Lead Status | The program must allow users to update the status field of a lead with predefined options. | ✅ Yes |
| Update Notes | The program must provide an option to either add to or completely replace the notes field for an existing lead. | ✅ Yes |
| Immediate Feedback | After every action, the program must display a message confirming success or failure. | ✅ Yes |
| Error Handling for Inputs | If the user inputs an invalid email, status, or note action, the program must display a clear error message and prompt the user to retry. | ✅ Yes |
| Date Auto-Update | When updating a lead's status, the program must automatically update the "Latest Contact" field with the current date. | ✅ Yes |
| Efficient Database Loading | The program must bypass Notion’s "load more" limitation by directly querying the full database via the API. | ✅ Yes |
| Seamless Database Switching | If a company check is required, the program must automatically switch to the company sales list database and return to the leads database afterward. | ✅ Yes |
| Predefined Status Options | The program must restrict status updates to a fixed set of options (e.g., "Not Sent," "E-mail 1," "Meeting Booked") to maintain data consistency. | ✅ Yes |
This program has a total of 9 user inputs. Each input has been tested according to the list below. The test results are below.
Validation Test for Inputs:
- a letter
a - multiple letters
abc - a number
1 - multiple numbers
123 - an empty ENTER with nothing
ENTER - only spaces
- special characters
?!@
Not any that I know of, please let me know if you find any!
This project has already proven incredibly helpful in streamlining my workflow, and I see great potential in further developing it. Here are some of the enhancements I plan to implement in the future:
One significant improvement would be the ability to automatically send emails directly from Outlook using predefined templates. This could include sending a batch of emails at once, further streamlining the workflow by removing the need to switch between the program and Outlook.
Integrating this program with a Upsales, a CRM program we use, would provide Key Account Managers with seamless access to lead activity. This would allow for better tracking, visibility, and collaboration across teams, enhancing the overall effectiveness of the lead management process.
Another enhancement would be to set up automated reminders for follow-ups. For example, if a lead hasn’t responded within a week, the program could send a notification or even a follow-up email automatically. This feature would help ensure that no leads are overlooked and that timely follow-ups are maintained.
To improve accuracy and save time, the program could be extended to automatically update the "Latest Contact" date field. This update could be based on when an email is sent to or received from a lead, ensuring that the database always reflects the most recent interaction without manual input.
This project utilizes Git and Gitpod for version control and to push code to the main repository. To maintain a clear and organized commit history, the project follows the Conventional Commits specification.
The following commit types are used in this project to describe changes:
| Commit Type | Purpose |
|---|---|
| feat | Adding a new feature to the program. |
| fix | Resolving bugs or errors in the code. |
| refactor | Improving the structure of the code, such as cleaning up, adding comments, or making changes that don't alter the program's functionality. |
| doc | Updating documentation, including README, comments, or any other non-code-related updates. |
This project was deployed to Heroku CLI. The steps to deploy are as follows:
- Fork or clone this repository.
- Create an account at Heroku
- Click
Newto create a new app from the dashboard. - Choose a unique name for the app and select your region. Then click
Create app. - Go to
Settingsand navigate toConfig Vars. - Add the following information:
KEY = PORT : VALUE = 8000 - Navigate to buildpacks and add
PythonandNodeJSis this order. - Click
Deploy Branch. - Scroll to
Deployment Methodand selectGithub. - Scroll down to
Deploy. For this project, the automatic deploys was selected. - Done!
See the deployed program here: Notion Lead Manager
- ChatGPT
Utilized to assist with generating and refining text for this README.
- Code Institute
Provided a template that helped establish the program's user interface - Code Institute P3 Template.
- A huge thank you to my mentor, Rory Patrick, for providing invaluable guidance throughout this project.
- Special thanks to Code Institute, particularly the "Love Sandwiches" project, for helping me get started with Python and guiding me through the project process.




























