Ads Domain Overview
High Level Domain
What is the Ads Domain?
The Ads domain allows Org::Company (employers) to purchase sponsored placements on the Jod platform — showing image-based creatives on prime real estate on the website (home hero banner, job list banner, etc.).
It is a self-serve advertising platform with an admin moderation gate before any ad goes live. Ads are priced in Placement Credits (Visibility Credits) — the shared credit pool managed by the ::Billing domain.
Three Contexts
The Ads domain exposes functionality across three distinct contexts, each serving a different actor.
| Context | Actor | Responsibility |
|---|---|---|
employers | Org::UserProfile (employer) | Build campaigns, upload creatives, submit for review |
marketplace | Public / Identities::User | Ad is served to job seekers browsing the platform |
team | Identities::Admin | Manage placement inventory (slots & packages); review, approve, or reject campaigns |
Core Concepts
Campaign (Ads::Campaign)
A campaign is the top-level container created by an employer. It has a name, status, and a submission/approval workflow. A campaign has no dates of its own — dates belong to individual placements, since each placement can run for a different duration.
Placement (Ads::Placement)
A placement defines a named slot on the website where an ad can appear (e.g. home_hero, job_list). Placements are managed by admin and define the required image dimensions. This is the supply side.
| Key | Name | Required Size | Description | Prices |
|---|---|---|---|---|
home_hero | Home Page - Hero Banner | 1024x342 | Premium placement at the top of the home page, appearing above the fold for maximum visibility. | 3 Days (3d / 3 credits)Weekly (7d / 5 credits)10 Days (10d / 7 credits) |
home_after_hero | Home Page - After Hero Banner | 1024x683 | Strategic placement positioned right after the hero section on the home page. | 3 Days (3d / 2 credits)Weekly (7d / 4 credits)10 Days (10d / 6 credits) |
home_middle_rectangle | Home Page - Middle Rectangle | 1024x683 | Large format placement within the main content area of the home page. | 3 Days (3d / 2 credits)Weekly (7d / 4 credits)10 Days (10d / 6 credits) |
home_bottom_banner | Home Page - Bottom Banner | 1024x342 | Retention-focused banner at the bottom of the home page. | Weekly (7d / 2 credits) |
job_list_inline | Job List - Inline Banner | 1024x683 | Native-style ad appearing between listings in job search results. | Weekly (7d / 3 credits)10 Days (10d / 5 credits) |
job_detail_inline | Job Detail - Inline Banner | 1024x683 | High-engagement banner placed within the job description and details page. | Weekly (7d / 3 credits)10 Days (10d / 5 credits) |
contact_us_hero | Contact Us - Top Banner | 1024x342 | Header placement on the Contact Us landing page. | Weekly (7d / 2 credits) |
faq_top | FAQ - Top Banner | 1024x342 | Header placement at the top of the FAQ and support section. | Weekly (7d / 2 credits) |
Placement Price (Ads::PlacementPrice)
A placement price defines a deal for a given placement: how many days it runs and how many placement credits it costs. Admin manages prices per placement. Examples:
| Placement | Price | Duration | Credit Cost |
|---|---|---|---|
home_hero | 3 Days | 3 days | 3 credits |
home_hero | Weekly | 7 days | 5 credits |
home_hero | 10 Days | 10 days | 7 credits |
job_list | Weekly | 7 days | 3 credits |
Creative (Ads::Creative)
A creative is a reusable image asset uploaded to S3 by the employer. It belongs to a company and can be reused across multiple campaigns — the employer's creative library.
CampaignPlacement (Ads::CampaignPlacement)
The join between a campaign, a placement package, and a creative. Represents one concrete ad unit within a campaign — e.g. "run our February creative on the home hero banner using the Weekly package." It owns:
- the snapshotted credit cost (frozen at booking time)
- the actual start/end datetimes (
start_time/end_time, set at admin approval) - its own status (pending → scheduled → active → completed)
- destination URL, headline, and description
Relationship to Billing
Ads are priced in Placement Credits (placement_credits) — the same pool used by Careers job postings and Job Boost.
| Billing Event | Trigger | Details |
|---|---|---|
Grant | Company tops up placement credits | Via Billing::Product purchase + invoice payment |
Reserve | Campaign submitted for review | One hold per CampaignPlacement, locked until approved/rejected |
Release | Campaign rejected or cancelled | Reserved credits returned to available |
Consume | Daily, while placement is active | credit_cost_snapshot / duration_days credits/day per active CampaignPlacement |
Credits are reserved at submission (not at campaign creation, not at approval). This prevents overspend during the approval window — the company's credit balance is locked the moment they commit a campaign for review.
See Billing Overview for the full credit ledger lifecycle.
Glossary
| Term | Description |
|---|---|
| Campaign | Top-level advertising container owned by an Org::Company |
| Placement | A named ad slot on the website (supply side), managed by admin |
| Placement Price | A duration + credit cost deal for a placement (e.g. home_hero × 7 days = 5 credits) |
| Creative | A reusable image asset uploaded by the employer |
| CampaignPlacement | A concrete ad unit: one creative running on one placement price within a campaign |
| Credit Cost Snapshot | credit_cost copied from ads_placement_prices onto ads_campaign_placements at booking time — frozen for the campaign's lifetime |
| Requested Start Date | The employer's desired start datetime for all placements — stored as 00:00 SGT of the chosen date (employer inputs date only). Minimum: MIN_START_DATE_LEAD_TIME days (2) from today. If omitted, placements go live DEFAULT_START_DAYS_AFTER_APPROVAL day(s) after admin approves at 00:00 SGT. If admin approves after this datetime has passed, placements go live immediately at approval time. |
| Impression | Record created each time a CampaignPlacement is served to a page visitor |
| Viewed Impression | An impression where the ad entered the user's viewport (tracked via IntersectionObserver beacon) |
| Click | Record created when a user clicks an ad and is redirected to destination_url |
| Fair Rotation | Serving algorithm that picks the ad with the oldest last_served_at, ensuring equal exposure |
| CTR | Click-through rate: (total_clicks / total_impressions) × 100 |
| View Rate | (viewed_impressions / total_impressions) × 100 — how often an ad actually entered the viewport |