#
Automatic Propagation: Tags, Campaign & Budget
Three values are automatically assigned to videos via PostgreSQL triggers — no application code needed. They differ in when they fire and what they affect:
Tags propagate retroactively (to all existing videos). Campaign and budget are set at insert time only — they don't update videos that already exist.
#
How It Works
Add tag to blogger
↓
blogger_tags (INSERT)
↓
Trigger: propagate_blogger_tag_change_to_videos()
↓
video_tags (INSERT for all videos from this blogger)
New video created with blogger_id
↓
videos (INSERT)
↓
Trigger: propagate_blogger_tags_to_video()
↓
Fetch all tags from blogger_tags
↓
video_tags (INSERT for this video)
#
Database Triggers
#
Trigger 1: trigger_propagate_blogger_tags_on_video_insert
- Event: AFTER INSERT on
videos - Condition:
NEW.blogger_id IS NOT NULL - Action: Inserts all tags from
blogger_tagsfor this blogger intovideo_tags
#
Trigger 2: trigger_propagate_blogger_tags_on_video_update
- Event: AFTER UPDATE OF
blogger_idonvideos - Condition:
blogger_idchanged and is not NULL - Action: Removes old blogger's tags, adds new blogger's tags
#
Trigger 3: trigger_propagate_tag_add_to_videos
- Event: AFTER INSERT on
blogger_tags - Action: Adds new tag to all existing videos from this blogger
#
Trigger 4: trigger_propagate_tag_remove_from_videos
- Event: AFTER DELETE on
blogger_tags - Action: Removes the tag from all videos from this blogger
All inserts use ON CONFLICT DO NOTHING to handle duplicates gracefully.
#
Schema
#
blogger_tags
Links bloggers to tags. Changing this table triggers propagation to video_tags.
#
video_tags
Automatically maintained — do not write to directly.
#
Scenarios
Adding a tag to a blogger: Trigger fires → all existing videos get the tag immediately. All future videos will also get it on INSERT.
Removing a tag from a blogger: Trigger fires → tag removed from all videos from this blogger.
Changing a video's blogger_id: Old blogger's tags are removed; new blogger's tags are added.
Excel/Sheets import with blogger_id set: Trigger fires on INSERT → video automatically gets all blogger tags.
#
API
POST /blogger/set-tags
{
"tracking_id": "uuid",
"tag_ids": ["tag-uuid-1", "tag-uuid-2"]
}
This replaces all current tags (delete + insert). The triggers handle video propagation automatically.
#
Campaign Auto-Assignment
When a campaign is set on a blogger, every new video fetched for that blogger automatically gets campaign_tag set — via a BEFORE INSERT trigger on the videos table.
POST /blogger/set-campaign { tracking_id, campaign: "Q1 2026" }
↓
blogger_campaign (UPSERT: blogger_id + organization_id + campaign)
↓
[next video INSERT for this blogger]
↓
BEFORE INSERT trigger on videos
↓
SELECT campaign FROM blogger_campaign WHERE blogger_id = NEW.blogger_id
↓
SET NEW.campaign_tag = campaign
#
Key behavior
- Only affects future videos — existing videos are NOT updated
- If campaign is removed, future videos get
campaign_tag = NULL - Works for all sources: blogger tracking, Excel import, Sheets import — any INSERT on
videos
#
Schema
#
blogger_campaign
#
API
POST /blogger/set-campaign
{
"tracking_id": "uuid",
"campaign": "Q1 2026"
}
#
Budget Auto-Assignment
Works identically to campaign — a BEFORE INSERT trigger reads from blogger_budget and sets videos.budget on each new video.
POST /blogger/set-budget-per-video { tracking_id, budget_per_video: 5000 }
↓
blogger_budget (UPSERT: blogger_id + organization_id + budget_per_video)
↓
[next video INSERT for this blogger]
↓
BEFORE INSERT trigger on videos
↓
SELECT budget_per_video FROM blogger_budget WHERE blogger_id = NEW.blogger_id
↓
SET NEW.budget = budget_per_video
#
Key behavior
- Only affects future videos — existing videos are NOT updated
- Used to compute CPM/payout in analytics
#
Schema
#
blogger_budget
#
API
POST /blogger/set-budget-per-video
{
"tracking_id": "uuid",
"budget_per_video": 5000
}
#
Summary: All Three Propagation Mechanisms
blogger_tags (change)
↓ AFTER trigger
→ video_tags updated for ALL videos (retroactive)
blogger_campaign / blogger_budget (change)
↓ (no immediate effect on existing videos)
→ BEFORE INSERT trigger fires on next video INSERT
→ videos.campaign_tag / videos.budget set at creation time