Each period is an independent 30-day cycle starting on the date you choose (e.g. July 1 to July 30).
When it ends: 1) click Create Report for the finished period, 2) reset each account's views from Update Stats, 3) pick the start date of the next period.
📱
Select a client to view their accounts
Accounts are grouped by platform underneath each client.
📊 Update Stats
📊
Loading…
⚙️ Supabase Database Setup
Copy this code and paste it into the
SQL Editor
in the Supabase Dashboard then click Run
-- ════════════════════════════════════
-- SADA Growth Agency — Database Schema
-- ════════════════════════════════════
-- Clients table
create table public.clients (
id uuid default gen_random_uuid() primary key,
user_id uuid references auth.users(id) on delete cascade,
name text not null,
email text not null,
plan text default 'basic',
is_active boolean default true,
status text default 'active',
created_at timestamptz default now()
);
-- Add columns if the table already exists
alter table public.clients add column if not exists is_active boolean default true;
alter table public.clients add column if not exists status text default 'active';
alter table public.clients add column if not exists photo_url text;
-- Storage bucket for client profile photos (public read)
insert into storage.buckets (id, name, public)
values ('client-avatars', 'client-avatars', true)
on conflict (id) do nothing;
-- Allow the SADA admin to upload/replace/delete client avatar photos
drop policy if exists "admin_manage_avatars" on storage.objects;
create policy "admin_manage_avatars" on storage.objects
for all
using (bucket_id = 'client-avatars' and auth.jwt()->>'email' = 'omar.alagha@metu.edu.tr')
with check (bucket_id = 'client-avatars' and auth.jwt()->>'email' = 'omar.alagha@metu.edu.tr');
-- Platform accounts table
create table public.client_accounts (
id uuid default gen_random_uuid() primary key,
client_id uuid references public.clients(id) on delete cascade,
platform text not null,
account_name text not null,
account_handle text,
account_url text,
platform_id text,
sort_order int default 0,
created_at timestamptz default now()
);
-- Add the ordering column if the table already exists (controls the order
-- accounts appear in, per platform — set by the admin via "Save Order")
alter table public.client_accounts add column if not exists sort_order int default 0;
-- Statistics table
create table public.account_stats (
id uuid default gen_random_uuid() primary key,
account_id uuid references public.client_accounts(id) on delete cascade,
views bigint default 0,
likes bigint default 0,
followers bigint default 0,
videos_count int default 0,
date_recorded date default current_date,
created_at timestamptz default now()
);
-- Enable RLS
alter table public.clients enable row level security;
alter table public.client_accounts enable row level security;
alter table public.account_stats enable row level security;
-- Client policy (can only see their own data)
create policy "client_own" on public.clients
for select using (auth.uid() = user_id);
create policy "accounts_own" on public.client_accounts
for select using (
exists (select 1 from public.clients
where id = client_id and user_id = auth.uid())
);
create policy "stats_own" on public.account_stats
for select using (
exists (
select 1 from public.client_accounts ca
join public.clients c on c.id = ca.client_id
where ca.id = account_id and c.user_id = auth.uid()
)
);
-- Full write access for admin (service_role)
-- Added automatically via the service role key in Supabase
-- Automatically link the client on signup
create or replace function public.link_client_on_signup()
returns trigger as $$
begin
update public.clients
set user_id = new.id
where email = new.email and user_id is null;
return new;
end;
$$ language plpgsql security definer;
create trigger on_auth_user_created
after insert on auth.users
for each row execute function public.link_client_on_signup();
-- ── Reporting period + client reports ──
-- Start date of each client's current 30-day reporting cycle
alter table public.clients add column if not exists report_period_start date;
-- Saved reports (generated by the admin, visible to the client)
create table if not exists public.client_reports (
id uuid default gen_random_uuid() primary key,
client_id uuid references public.clients(id) on delete cascade,
period_start date,
period_end date,
report_data jsonb not null,
created_at timestamptz default now()
);
alter table public.client_reports enable row level security;
drop policy if exists "reports_own" on public.client_reports;
create policy "reports_own" on public.client_reports
for select using (
exists (select 1 from public.clients
where id = client_id and user_id = auth.uid())
);
drop policy if exists "reports_admin" on public.client_reports;
create policy "reports_admin" on public.client_reports
for all
using (auth.jwt()->>'email' = 'omar.alagha@metu.edu.tr')
with check (auth.jwt()->>'email' = 'omar.alagha@metu.edu.tr');
After running the code, add your email in Supabase → Authentication → Users as admin
➕ Add New Client
?
After adding, send the client their email and password to access their dashboard directly. No registration is needed.
📱 Add Account
Adding account for:
Find it in YouTube Studio → Your Channel → About → Share Channel