Skip to Content
BacklinksBacklink Opportunity Database

Backlink Opportunity Database

Status: [To Build]

A curated, admin-managed database of directories, listing sites, social bookmarking platforms, and press release sites where clients can self-serve build backlinks. An AI agent matches each tenant’s domain, region, and business type to the most relevant entries and surfaces them directly in the existing backlinks list as sourceType: "directory_opportunity" or "competitor_gap" rows.


Concept

The existing pipeline handles cold outreach (DM sends emails on behalf of the client). This feature handles self-serve link building — a curated list of sites the client can go to themselves and submit their business, with step-by-step instructions for each.

Cold Outreach PipelineOpportunity Database
Who actsDM sends emailsClient submits themselves
DiscoveryAI researches arbitrary domainsPre-seeded + agent-filtered from DB
OutputCampaignEmail for DM to sendSteps panel on detail page
Status flowprospecting → outreach_sent → agreed → publishedopportunity → in_progress → completed
UI surfaceSame backlinks list + detailSame backlinks list + detail

Both types live on the same /seo/backlinks page. sourceType determines which detail panels are shown.


Directory Database Structure

Categories (from spreadsheet)

CategorySubcategories
Business Directories / Listing SitesAutomotive, Creative Services, Education & Training, Events & Entertainment, Finance & Accounting, Food & Hospitality, Healthcare/Medical, Home Services & Construction, IT & Software/SaaS, Legal, Marketing Tech, Real Estate, Travel & Tourism, Other
Social Bookmarking SitesGeneral, News Aggregators & Trend Curators, Image & Visual Content, Tech & Developer-Focused, Professional & Academic, Business & Marketing, Social Media/Community Sharing Platforms
Press ReleaseAutomotive, E-commerce & Retail, Education & EdTech, Entertainment & Media, Environment & Sustainability, Finance & Fintech, Healthcare & Medical, Legal & Regulatory, Manufacturing & Industrial, Nonprofits & Social Impact, Real Estate, Technology, Travel & Hospitality, Other

Additional planned categories:

  • Forum & Community Sites (Reddit, Quora, Stack Overflow, niche forums)
  • Review Platforms (G2, Capterra, Trustpilot, Google Business Profile)
  • Resource / Wiki Sites (Wikipedia citations, AboutUs, Crunchbase)

Data Model

BacklinkDirectory

Table: backlink_directory
Managed by superadmins. Tenant-agnostic.

FieldTypeNotes
idString (cuid)PK
nameStringDisplay name, e.g. “HealthGrades”
urlStringSubmission/listing URL
categoryStringbusiness_directory | social_bookmarking | press_release | forum | review_platform | resource_site
subcategoryStringIndustry/topic subcategory from the table above
domainRatingInt?0–100; used in “What You Gain” panel
linkTypeStringdofollow | nofollow (default: nofollow)
isFreeBooleanWhether free submission is available
isPaidBooleanWhether there’s a paid tier (not mutually exclusive with isFree)
paidPriceUsdInt?Approximate paid listing cost in USD
regionsString[]["IN", "US", "GLOBAL"] — applicable countries/regions
difficultyStringeasy | medium | hard — effort to get listed
estimatedMinutesInt?Approximate time to complete submission
stepsJsonOrdered array of { order, title, description, url? }
isActiveBooleanToggle visibility across all tenants (default: true)
createdAtDateTime
updatedAtDateTime

Indexes:

  • [category, subcategory] — agent filtering
  • [regions] — region-based filtering
  • [isActive]

Steps JSON shape

type DirectoryStep = { order: number title: string description: string url?: string // direct link to the page to visit for this step }

Example:

[ { "order": 1, "title": "Go to the submission page", "description": "Visit the business listing form.", "url": "https://example-directory.com/add-listing" }, { "order": 2, "title": "Create an account", "description": "Sign up with your business email. Use the same domain as your website." }, { "order": 3, "title": "Fill in business details", "description": "Enter your business name, website URL, description (150–300 words), and select your category." }, { "order": 4, "title": "Submit for review", "description": "Click Submit. Approval typically takes 2–5 business days. You'll receive a confirmation email." } ]

Three new fields added to the existing Backlink model:

FieldTypeNotes
sourceTypeStringoutreach | directory_opportunity | competitor_gap (default: outreach)
directoryIdString?FK → BacklinkDirectory (null for outreach and agent-discovered competitor_gap)
stepsJson?Copied from BacklinkDirectory.steps at opportunity-creation time; self-contained so edits to the directory don’t retroactively change the backlink

Why copy steps onto the Backlink row: The directory entry may be edited or deactivated. Each Backlink row preserves the instructions that were current when it was created.

Status values by sourceType:

sourceTypeoutreachStatus values
outreachprospectingoutreach_sentrespondedagreedpublished (also: rejected, no_response)
directory_opportunityopportunityin_progresscompleted | not_applicable
competitor_gapopportunityin_progresscompleted | not_applicable

Agent: opportunity-matcher

Queue: agent__opportunity_matcher
Credit type: backlink_opportunity_match
Trigger: On-demand (DM or client initiates) or post-onboarding setup chain

Input: { tenantId } — agent loads tenant domain, region, business category, and client context internally.

Process:

  1. Directory filtering: Query BacklinkDirectory where isActive = true and regions contains the tenant’s region (or "GLOBAL"). Filter by subcategory match against the tenant’s business type.
  2. Deduplication: Skip directories where a Backlink row already exists for this tenant (directoryId match).
  3. Relevance scoring: LLM scores each filtered directory 1–10 based on client context + business type. Drops entries scoring < 4.
  4. Competitor gap discovery: Crawl competitor domains (from Tenant.competitors) and find listing sites they appear on that are not in the BacklinkDirectory DB — propose these as sourceType: "competitor_gap" rows.
  5. Backlink row creation: For each result, insert a Backlink row with sourceType, directoryId, steps (copied), relevanceScore, outreachStatus: "opportunity", domainRating, linkType.

Output: N new Backlink rows; no email, no campaign created.


Manage Portal — Directory Management

Route: /templates/backlink-directories (or /settings/backlink-directories)

ScreenDescription
Directory listTable of all BacklinkDirectory entries; filter by category/region/active; toggle active inline
Add directoryForm: name, URL, category, subcategory, DR, link type, free/paid, regions, difficulty, estimated minutes, steps builder
Edit directorySame form; changes do NOT retroactively update existing Backlink.steps copies
Bulk CSV importUpload CSV matching the spreadsheet format; maps columns to model fields
Steps builderDrag-and-drop ordered list of steps; each step has title + description + optional URL

Seeding Plan

The spreadsheet defines ~3 category groups × ~10 subcategories. Initial seed data will cover approximately:

  • 200–300 Business Directory entries (one per major industry subcategory × top 15–20 directories)
  • 50–80 Social Bookmarking entries (top bookmarking/aggregator sites per subcategory)
  • 30–50 Press Release sites (free + paid tiers)

Seed file: packages/db/prisma/seed/backlink-directories.ts
Format: array of BacklinkDirectory objects matching the model fields above.

© 2026 Leadmetrics — Internal use only