-- Preview fields for creatives pipeline (ads + RRSS placement mocks) -- Idempotent. alter table public.creatives add column if not exists channel text; alter table public.creatives add column if not exists placement text; alter table public.creatives add column if not exists format text; alter table public.creatives add column if not exists headline text; alter table public.creatives add column if not exists primary_text text; alter table public.creatives add column if not exists description text; alter table public.creatives add column if not exists cta text; alter table public.creatives add column if not exists media_url text; alter table public.creatives add column if not exists brand_name text; alter table public.creatives add column if not exists landing_url text; alter table public.creatives add column if not exists meta jsonb not null default '{}'::jsonb; -- Soft checks (nullable for legacy rows) do $$ begin if not exists ( select 1 from pg_constraint where conname = 'creatives_channel_check' ) then alter table public.creatives add constraint creatives_channel_check check ( channel is null or channel in ( 'meta_ads', 'google_ads', 'instagram', 'facebook', 'linkedin', 'tiktok', 'stories', 'other' ) ); end if; end $$; do $$ begin if not exists ( select 1 from pg_constraint where conname = 'creatives_format_check' ) then alter table public.creatives add constraint creatives_format_check check ( format is null or format in ( 'image', 'video', 'carousel', 'reel', 'story', 'rsa', 'pmax', 'other' ) ); end if; end $$; comment on column public.creatives.channel is 'Surface: meta_ads | google_ads | instagram | facebook | linkedin | stories…'; comment on column public.creatives.placement is 'Placement mock: feed | stories | reels | search | display…'; comment on column public.creatives.media_url is 'Public or signed URL for creative media preview';