Audience Management — Technical Documentation
Last updated: February 2026
Table of Contents
- Overview
- Architecture
- Repository Map
- Core Flows
- Entities & Data Model
- API Endpoints
- Services & Business Logic
- ClickHouse Integration
- Configuration
- Integration Points
1. Overview
Audience Management handles the full lifecycle of prospect target groups — creation, prospect imports, deduplication (engaged/in-other-audiences/remaining), statistics recalculation, ClickHouse sync, status transitions, and webhook triggers. It spans two repositories: sopromasterdata (backend API + Hangfire jobs) and data-admin (React frontend).
2. Architecture
3. Repository Map
| Repository | Layer | Key Files |
|---|---|---|
| sopromasterdata | API Controller | API/SoProMasterDBAPI/Controllers/AudienceController.cs |
| sopromasterdata | Admin Controller | API/SoProMasterDBAPI/Controllers/AudienceAdminController.cs |
| sopromasterdata | Service | AudienceServices/AudienceService.cs |
| sopromasterdata | Hangfire Service | HangfireServices/AudienceHangfireService.cs |
| sopromasterdata | Repository | Repository/Audience/AudienceRepository.cs |
| sopromasterdata | Contact Repository | Repository/Audience/AudienceContactRepository.cs |
| sopromasterdata | Entities | AudienceEntities/Audience.cs, AudienceContact.cs |
| sopromasterdata | ClickHouse | Clickhouse/AudienceClickhouseService.cs |
| data-admin | Pages | src/pages/audiences/ |
| data-admin | API Hooks | src/api/audience.queries.ts |
| data-admin | Types | src/types/audiences/ |
4. Core Flows
4.1 Audience Creation Flow
4.2 Import & Deduplication Flow
4.3 Statistics Recalculation
5. Entities & Data Model
5.1 SQL Server Entities
Audience
| Column | Type | Description |
|---|---|---|
Id | int (PK) | Auto-increment primary key |
Name | nvarchar(255) | Audience display name |
ClientId | int (FK) | Linked client |
Status | int (enum) | Draft, Active, Paused, Completed |
CreatedAt | datetime | Creation timestamp |
UpdatedAt | datetime | Last modification timestamp |
CreatedBy | nvarchar(100) | User who created the audience |
AudienceContact
| Column | Type | Description |
|---|---|---|
Id | long (PK) | Auto-increment primary key |
AudienceId | int (FK) | Parent audience |
ProspectId | long (FK) | Link to prospect record |
Status | int (enum) | Engaged, InOtherAudience, Remaining |
ImportBatchId | int | Which import batch added this contact |
CreatedAt | datetime | When the contact was added |
AudienceFilter
| Column | Type | Description |
|---|---|---|
Id | int (PK) | Auto-increment primary key |
AudienceId | int (FK) | Parent audience |
FilterType | int (enum) | Type of filter (Industry, Title, Location, etc.) |
FilterValue | nvarchar(500) | Filter value |
AudienceStatistics
| Column | Type | Description |
|---|---|---|
Id | int (PK) | Auto-increment primary key |
AudienceId | int (FK) | Parent audience |
TotalProspects | int | Total prospect count |
EngagedCount | int | Count of engaged prospects |
InOtherAudiencesCount | int | Count in other audiences |
RemainingCount | int | Count of remaining prospects |
TargetCoverage | decimal | Coverage percentage |
CalculatedAt | datetime | Last calculation timestamp |
AudienceImport
| Column | Type | Description |
|---|---|---|
Id | int (PK) | Auto-increment primary key |
AudienceId | int (FK) | Parent audience |
ImportedCount | int | Number of prospects imported |
Source | nvarchar(100) | Data source identifier |
Status | int (enum) | Pending, Processing, Complete, Failed |
StartedAt | datetime | Import start time |
CompletedAt | datetime? | Import completion time |
5.2 ClickHouse Tables
audience_contacts (ClickHouse)
Used for fast analytics reads. Synced from SQL Server after imports.
| Column | Type | Description |
|---|---|---|
audience_id | UInt32 | Audience identifier |
prospect_id | UInt64 | Prospect identifier |
status | UInt8 | Contact status (enum) |
created_at | DateTime | Sync timestamp |
Engine: MergeTree() ordered by (audience_id, prospect_id)
6. API Endpoints
Public API (/api/Audience)
| Method | Endpoint | Description |
|---|---|---|
GET | /api/Audience/GetAudiences | List audiences with pagination |
GET | /api/Audience/GetAudienceById/{id} | Get audience detail |
GET | /api/Audience/GetAudienceContacts | Get contacts for an audience |
GET | /api/Audience/GetAudienceStatistics/{id} | Get statistics for an audience |
POST | /api/Audience/CreateAudience | Create a new audience |
Admin API (/api/admin/Audience)
| Method | Endpoint | Description |
|---|---|---|
GET | /api/admin/Audience/GetImportsByAudience/{id} | Get import history |
POST | /api/admin/Audience/RecalculateStatistics/{id} | Trigger stats recalculation |
POST | /api/admin/Audience/SyncToClickhouse/{id} | Manual ClickHouse sync |
7. Services & Business Logic
AudienceService
Location: AudienceServices/AudienceService.cs
Interface: IAudienceService
DI Registration: AddScoped<IAudienceService, AudienceService>() in ApiServiceExtensions.cs
Key methods:
| Method | Description |
|---|---|
CreateAudienceAsync() | Creates audience + filters, enqueues import job |
GetAudienceByIdAsync() | Returns audience with stats and filters |
GetAudienceContactsAsync() | Paginated contact list with search |
RecalculateStatisticsAsync() | Recounts all deduplication categories |
AudienceHangfireService
Location: HangfireServices/AudienceHangfireService.cs
Interface: IAudienceHangfireService
DI Registration: AddTransient<IAudienceHangfireService, AudienceHangfireService>()
Key methods:
| Method | Description |
|---|---|
RunImportJobAsync() | Imports prospects in batches, runs dedup |
RunDeduplicationAsync() | Categorizes contacts as engaged/other/remaining |
SyncToClickhouseAsync() | Syncs audience data to ClickHouse |
AudienceContactRepository
Location: Repository/Audience/AudienceContactRepository.cs
Interface: IAudienceContactRepository
Key methods:
| Method | Description |
|---|---|
GetContactsByAudienceAsync() | Paginated query with filters |
InsertBatchAsync() | Bulk insert contacts |
CheckDuplicatesAsync() | Check against engaged and other audiences |
GetDeduplicationCountsAsync() | Counts per category for statistics |
8. ClickHouse Integration
Audience data is synced to ClickHouse for fast analytical reads. The sync uses the Dapper-based ClickHouse service.
Service: IRepositoryDapperClickhouseDbService
Pattern: Always use Dapper, never raw ExecuteReader
// Example: Querying ClickHouse for audience stats
await _dapperClickhouseDbService.Get<AudienceStatsDto>(
"SELECT audience_id, count() as total FROM audience_contacts WHERE audience_id = @audienceId GROUP BY audience_id",
new Dictionary<string, object> { { "audienceId", audienceId } },
useCache: false,
provider: DbProvider.Clickhouse
);
Sync trigger: After import completion and statistics recalculation.
9. Configuration
DI Registration
DataApi: API/SoProMasterDBAPI/Extensions/ApiServiceExtensions.cs
services.AddScoped<IAudienceService, AudienceService>();
services.AddScoped<IAudienceRepository, AudienceRepository>();
services.AddScoped<IAudienceContactRepository, AudienceContactRepository>();
Hangfire: Registered as AddTransient for background job isolation.
Frontend Configuration
API Hooks: src/api/audience.queries.ts
Endpoints: src/api/endpoints.ts → endpoints.audiences
10. Integration Points
Upstream (data flows in)
| Source | Data | Mechanism |
|---|---|---|
| Prospect Database | Prospect records matching audience filters | SQL query during import |
| Campaign System | Engaged status (which prospects are in active campaigns) | Deduplication check at import |
Downstream (data flows out)
| Target | Data | Mechanism |
|---|---|---|
| ClickHouse | Audience contact data for fast analytics | Dapper-based sync after import |
| Campaign Management | Audience linked to campaign for outreach | Foreign key relationship |
| Data Admin UI | Audience stats, contacts, import history | REST API → React Query |
Cross-Feature Dependencies
| Feature | Relationship |
|---|---|
| Campaign Management | Campaigns link to audiences; campaign status affects dedup |
| Verification Pipeline | Verified email status can affect prospect availability |
| Search & Filters | Audience targeting uses the same filter system |