Acquisition KPIs are powered by Google Analytics 4. Once GA4 is configured with enhanced e-commerce tracking, these metrics will populate automatically.
Revenue KPIs are powered by Stripe. Once Stripe webhooks are configured and subscription events are flowing, these metrics will populate automatically.
Track MRR, ARPU, and subscription changes
Monitor churn with automated alerts
Analyze LTV with cohort analysis'),Ie=I('
Pending
—
Target: ');const xe=[{key:"mrr",label:"Monthly Recurring Revenue",target:"$550K by EOY",unit:"USD"},{key:"churn_rate",label:"Monthly Churn Rate",target:"<3%",unit:"%"},{key:"ltv",label:"Customer Lifetime Value",target:">$120",unit:"USD"},{key:"arpu",label:"Avg Revenue Per User",target:"Growing",unit:"USD"},{key:"upgrades",label:"Plan Upgrades",target:">10% MoM",unit:"%"}],Le=()=>(()=>{var r=we(),e=r.firstChild,t=e.nextSibling;return f(t,()=>xe.map(i=>(()=>{var u=Ie(),l=u.firstChild,p=l.firstChild,c=l.nextSibling,d=c.nextSibling;return d.firstChild,f(p,()=>i.label),f(d,()=>i.target,null),u})())),r})(),o=Symbol.for("drizzle:entityKind");function _(r,e){if(!r||typeof r!="object")return!1;if(r instanceof e)return!0;if(!Object.prototype.hasOwnProperty.call(e,o))throw new Error(`Class "${e.name??""}" doesn't look like a Drizzle entity. If this is incorrect and the class is provided by Drizzle, please report this as a bug.`);let t=Object.getPrototypeOf(r).constructor;if(t)for(;t;){if(o in t&&t[o]===e[o])return!0;t=Object.getPrototypeOf(t)}return!1}class J{constructor(e,t){this.table=e,this.config=t,this.name=t.name,this.keyAsName=t.keyAsName,this.notNull=t.notNull,this.default=t.default,this.defaultFn=t.defaultFn,this.onUpdateFn=t.onUpdateFn,this.hasDefault=t.hasDefault,this.primary=t.primaryKey,this.isUnique=t.isUnique,this.uniqueName=t.uniqueName,this.uniqueType=t.uniqueType,this.dataType=t.dataType,this.columnType=t.columnType,this.generated=t.generated,this.generatedIdentity=t.generatedIdentity}static[o]="Column";name;keyAsName;primary;notNull;default;defaultFn;onUpdateFn;hasDefault;isUnique;uniqueName;uniqueType;dataType;columnType;enumValues=void 0;generated=void 0;generatedIdentity=void 0;config;mapFromDriverValue(e){return e}mapToDriverValue(e){return e}shouldDisableInsert(){return this.config.generated!==void 0&&this.config.generated.type!=="byDefault"}}class Qe{static[o]="ColumnBuilder";config;constructor(e,t,i){this.config={name:e,keyAsName:e==="",notNull:!1,default:void 0,hasDefault:!1,primaryKey:!1,isUnique:!1,uniqueName:void 0,uniqueType:void 0,dataType:t,columnType:i,generated:void 0}}$type(){return this}notNull(){return this.config.notNull=!0,this}default(e){return this.config.default=e,this.config.hasDefault=!0,this}$defaultFn(e){return this.config.defaultFn=e,this.config.hasDefault=!0,this}$default=this.$defaultFn;$onUpdateFn(e){return this.config.onUpdateFn=e,this.config.hasDefault=!0,this}$onUpdate=this.$onUpdateFn;primaryKey(){return this.config.primaryKey=!0,this.config.notNull=!0,this}setName(e){this.config.name===""&&(this.config.name=e)}}const Q=Symbol.for("drizzle:Name"),Z=Symbol.for("drizzle:isPgEnum");function Be(r){return!!r&&typeof r=="function"&&Z in r&&r[Z]===!0}class se{static[o]="Subquery";constructor(e,t,i,u=!1,l=[]){this._={brand:"Subquery",sql:e,selectedFields:t,alias:i,isWith:u,usedTables:l}}}const De={startActiveSpan(r,e){return e()}},B=Symbol.for("drizzle:ViewBaseConfig"),z=Symbol.for("drizzle:Schema"),ee=Symbol.for("drizzle:Columns"),te=Symbol.for("drizzle:ExtraConfigColumns"),U=Symbol.for("drizzle:OriginalName"),V=Symbol.for("drizzle:BaseName"),$=Symbol.for("drizzle:IsAlias"),re=Symbol.for("drizzle:ExtraConfigBuilder"),Te=Symbol.for("drizzle:IsDrizzleTable");class S{static[o]="Table";static Symbol={Name:Q,Schema:z,OriginalName:U,Columns:ee,ExtraConfigColumns:te,BaseName:V,IsAlias:$,ExtraConfigBuilder:re};[Q];[U];[z];[ee];[te];[V];[$]=!1;[Te]=!0;[re]=void 0;constructor(e,t,i){this[Q]=this[U]=e,this[z]=t,this[V]=i}}function Ae(r){return r!=null&&typeof r.getSQL=="function"}function Ce(r){const e={sql:"",params:[]};for(const t of r)e.sql+=t.sql,e.params.push(...t.params),t.typings?.length&&(e.typings||(e.typings=[]),e.typings.push(...t.typings));return e}class v{static[o]="StringChunk";value;constructor(e){this.value=Array.isArray(e)?e:[e]}getSQL(){return new y([this])}}class y{constructor(e){this.queryChunks=e;for(const t of e)if(_(t,S)){const i=t[S.Symbol.Schema];this.usedTables.push(i===void 0?t[S.Symbol.Name]:i+"."+t[S.Symbol.Name])}}static[o]="SQL";decoder=oe;shouldInlineParams=!1;usedTables=[];append(e){return this.queryChunks.push(...e.queryChunks),this}toQuery(e){return De.startActiveSpan("drizzle.buildSQL",t=>{const i=this.buildQueryFromSourceParams(this.queryChunks,e);return t?.setAttributes({"drizzle.query.text":i.sql,"drizzle.query.params":JSON.stringify(i.params)}),i})}buildQueryFromSourceParams(e,t){const i=Object.assign({},t,{inlineParams:t.inlineParams||this.shouldInlineParams,paramStartIndex:t.paramStartIndex||{value:0}}),{casing:u,escapeName:l,escapeParam:p,prepareTyping:c,inlineParams:d,paramStartIndex:h}=i;return Ce(e.map(s=>{if(_(s,v))return{sql:s.value.join(""),params:[]};if(_(s,O))return{sql:l(s.value),params:[]};if(s===void 0)return{sql:"",params:[]};if(Array.isArray(s)){const m=[new v("(")];for(const[g,q]of s.entries())m.push(q),gr},le={mapToDriverValue:r=>r};({...oe,...le});class ue{constructor(e,t=le){this.value=e,this.encoder=t}static[o]="Param";brand;getSQL(){return new y([this])}}function R(r,...e){const t=[];(e.length>0||r.length>0&&r[0]!=="")&&t.push(new v(r[0]));for(const[i,u]of e.entries())t.push(u,new v(r[i+1]));return new y(t)}(r=>{function e(){return new y([])}r.empty=e;function t(d){return new y(d)}r.fromList=t;function i(d){return new y([new v(d)])}r.raw=i;function u(d,h){const s=[];for(const[m,g]of d.entries())m>0&&h!==void 0&&s.push(h),s.push(g);return new y(s)}r.join=u;function l(d){return new O(d)}r.identifier=l;function p(d){return new j(d)}r.placeholder=p;function c(d,h){return new ue(d,h)}r.param=c})(R||(R={}));(r=>{class e{constructor(i,u){this.sql=i,this.fieldAlias=u}static[o]="SQL.Aliased";isSelectionField=!1;getSQL(){return this.sql}clone(){return new e(this.sql,this.fieldAlias)}}r.Aliased=e})(y||(y={}));class j{constructor(e){this.name=e}static[o]="Placeholder";getSQL(){return new y([this])}}const $e=Symbol.for("drizzle:IsDrizzleView");class Pe{static[o]="View";[B];[$e]=!0;constructor({name:e,schema:t,selectedFields:i,query:u}){this[B]={name:e,originalName:e,schema:t,selectedFields:i,query:u,isExisting:!u,isAlias:!1}}getSQL(){return new y([this])}}J.prototype.getSQL=function(){return new y([this])};S.prototype.getSQL=function(){return new y([this])};se.prototype.getSQL=function(){return new y([this])};function A(r,e){return{name:typeof r=="string"&&r.length>0?r:"",config:typeof r=="object"?r:e}}const de=typeof TextDecoder>"u"?null:new TextDecoder;class qe{static[o]="SQLiteForeignKeyBuilder";reference;_onUpdate;_onDelete;constructor(e,t){this.reference=()=>{const{name:i,columns:u,foreignColumns:l}=e();return{name:i,columns:u,foreignTable:l[0].table,foreignColumns:l}},t&&(this._onUpdate=t.onUpdate,this._onDelete=t.onDelete)}onUpdate(e){return this._onUpdate=e,this}onDelete(e){return this._onDelete=e,this}build(e){return new Ke(e,this)}}class Ke{constructor(e,t){this.table=e,this.reference=t.reference,this.onUpdate=t._onUpdate,this.onDelete=t._onDelete}static[o]="SQLiteForeignKey";reference;onUpdate;onDelete;getName(){const{name:e,columns:t,foreignColumns:i}=this.reference(),u=t.map(c=>c.name),l=i.map(c=>c.name),p=[this.table[Q],...u,i[0].table[Q],...l];return e??`${p.join("_")}_fk`}}function ke(r,e){return`${r[Q]}_${e.join("_")}_unique`}class N extends Qe{static[o]="SQLiteColumnBuilder";foreignKeyConfigs=[];references(e,t={}){return this.foreignKeyConfigs.push({ref:e,actions:t}),this}unique(e){return this.config.isUnique=!0,this.config.uniqueName=e,this}generatedAlwaysAs(e,t){return this.config.generated={as:e,type:"always",mode:t?.mode??"virtual"},this}buildForeignKeys(e,t){return this.foreignKeyConfigs.map(({ref:i,actions:u})=>((l,p)=>{const c=new qe(()=>{const d=l();return{columns:[e],foreignColumns:[d]}});return p.onUpdate&&c.onUpdate(p.onUpdate),p.onDelete&&c.onDelete(p.onDelete),c.build(t)})(i,u))}}class w extends J{constructor(e,t){t.uniqueName||(t.uniqueName=ke(e,[t.name])),super(e,t),this.table=e}static[o]="SQLiteColumn"}class Fe extends N{static[o]="SQLiteBigIntBuilder";constructor(e){super(e,"bigint","SQLiteBigInt")}build(e){return new ze(e,this.config)}}class ze extends w{static[o]="SQLiteBigInt";getSQLType(){return"blob"}mapFromDriverValue(e){if(typeof Buffer<"u"&&Buffer.from){const t=Buffer.isBuffer(e)?e:e instanceof ArrayBuffer?Buffer.from(e):e.buffer?Buffer.from(e.buffer,e.byteOffset,e.byteLength):Buffer.from(e);return BigInt(t.toString("utf8"))}return BigInt(de.decode(e))}mapToDriverValue(e){return Buffer.from(e.toString())}}class Ue extends N{static[o]="SQLiteBlobJsonBuilder";constructor(e){super(e,"json","SQLiteBlobJson")}build(e){return new Ve(e,this.config)}}class Ve extends w{static[o]="SQLiteBlobJson";getSQLType(){return"blob"}mapFromDriverValue(e){if(typeof Buffer<"u"&&Buffer.from){const t=Buffer.isBuffer(e)?e:e instanceof ArrayBuffer?Buffer.from(e):e.buffer?Buffer.from(e.buffer,e.byteOffset,e.byteLength):Buffer.from(e);return JSON.parse(t.toString("utf8"))}return JSON.parse(de.decode(e))}mapToDriverValue(e){return Buffer.from(JSON.stringify(e))}}class Oe extends N{static[o]="SQLiteBlobBufferBuilder";constructor(e){super(e,"buffer","SQLiteBlobBuffer")}build(e){return new Re(e,this.config)}}class Re extends w{static[o]="SQLiteBlobBuffer";mapFromDriverValue(e){return Buffer.isBuffer(e)?e:Buffer.from(e)}getSQLType(){return"blob"}}function je(r,e){const{name:t,config:i}=A(r,e);return i?.mode==="json"?new Ue(t):i?.mode==="bigint"?new Fe(t):new Oe(t)}class Ee extends N{static[o]="SQLiteCustomColumnBuilder";constructor(e,t,i){super(e,"custom","SQLiteCustomColumn"),this.config.fieldConfig=t,this.config.customTypeParams=i}build(e){return new Me(e,this.config)}}class Me extends w{static[o]="SQLiteCustomColumn";sqlName;mapTo;mapFrom;constructor(e,t){super(e,t),this.sqlName=t.customTypeParams.dataType(t.fieldConfig),this.mapTo=t.customTypeParams.toDriver,this.mapFrom=t.customTypeParams.fromDriver}getSQLType(){return this.sqlName}mapFromDriverValue(e){return typeof this.mapFrom=="function"?this.mapFrom(e):e}mapToDriverValue(e){return typeof this.mapTo=="function"?this.mapTo(e):e}}function Je(r){return(e,t)=>{const{name:i,config:u}=A(e,t);return new Ee(i,u,r)}}class G extends N{static[o]="SQLiteBaseIntegerBuilder";constructor(e,t,i){super(e,t,i),this.config.autoIncrement=!1}primaryKey(e){return e?.autoIncrement&&(this.config.autoIncrement=!0),this.config.hasDefault=!0,super.primaryKey()}}class W extends w{static[o]="SQLiteBaseInteger";autoIncrement=this.config.autoIncrement;getSQLType(){return"integer"}}class Ge extends G{static[o]="SQLiteIntegerBuilder";constructor(e){super(e,"number","SQLiteInteger")}build(e){return new We(e,this.config)}}class We extends W{static[o]="SQLiteInteger"}class He extends G{static[o]="SQLiteTimestampBuilder";constructor(e,t){super(e,"date","SQLiteTimestamp"),this.config.mode=t}defaultNow(){return this.default(R`(cast((julianday('now') - 2440587.5)*86400000 as integer))`)}build(e){return new Ye(e,this.config)}}class Ye extends W{static[o]="SQLiteTimestamp";mode=this.config.mode;mapFromDriverValue(e){return this.config.mode==="timestamp"?new Date(e*1e3):new Date(e)}mapToDriverValue(e){const t=e.getTime();return this.config.mode==="timestamp"?Math.floor(t/1e3):t}}class Xe extends G{static[o]="SQLiteBooleanBuilder";constructor(e,t){super(e,"boolean","SQLiteBoolean"),this.config.mode=t}build(e){return new Ze(e,this.config)}}class Ze extends W{static[o]="SQLiteBoolean";mode=this.config.mode;mapFromDriverValue(e){return Number(e)===1}mapToDriverValue(e){return e?1:0}}function n(r,e){const{name:t,config:i}=A(r,e);return i?.mode==="timestamp"||i?.mode==="timestamp_ms"?new He(t,i.mode):i?.mode==="boolean"?new Xe(t,i.mode):new Ge(t)}class et extends N{static[o]="SQLiteNumericBuilder";constructor(e){super(e,"string","SQLiteNumeric")}build(e){return new tt(e,this.config)}}class tt extends w{static[o]="SQLiteNumeric";mapFromDriverValue(e){return typeof e=="string"?e:String(e)}getSQLType(){return"numeric"}}class rt extends N{static[o]="SQLiteNumericNumberBuilder";constructor(e){super(e,"number","SQLiteNumericNumber")}build(e){return new nt(e,this.config)}}class nt extends w{static[o]="SQLiteNumericNumber";mapFromDriverValue(e){return typeof e=="number"?e:Number(e)}mapToDriverValue=String;getSQLType(){return"numeric"}}class it extends N{static[o]="SQLiteNumericBigIntBuilder";constructor(e){super(e,"bigint","SQLiteNumericBigInt")}build(e){return new at(e,this.config)}}class at extends w{static[o]="SQLiteNumericBigInt";mapFromDriverValue=BigInt;mapToDriverValue=String;getSQLType(){return"numeric"}}function st(r,e){const{name:t,config:i}=A(r,e),u=i?.mode;return u==="number"?new rt(t):u==="bigint"?new it(t):new et(t)}class ot extends N{static[o]="SQLiteRealBuilder";constructor(e){super(e,"number","SQLiteReal")}build(e){return new lt(e,this.config)}}class lt extends w{static[o]="SQLiteReal";getSQLType(){return"real"}}function T(r){return new ot(r??"")}class ut extends N{static[o]="SQLiteTextBuilder";constructor(e,t){super(e,"string","SQLiteText"),this.config.enumValues=t.enum,this.config.length=t.length}build(e){return new dt(e,this.config)}}class dt extends w{static[o]="SQLiteText";enumValues=this.config.enumValues;length=this.config.length;constructor(e,t){super(e,t)}getSQLType(){return`text${this.config.length?`(${this.config.length})`:""}`}}class ct extends N{static[o]="SQLiteTextJsonBuilder";constructor(e){super(e,"json","SQLiteTextJson")}build(e){return new mt(e,this.config)}}class mt extends w{static[o]="SQLiteTextJson";getSQLType(){return"text"}mapFromDriverValue(e){return JSON.parse(e)}mapToDriverValue(e){return JSON.stringify(e)}}function a(r,e={}){const{name:t,config:i}=A(r,e);return i.mode==="json"?new ct(t):new ut(t,i)}function pt(){return{blob:je,customType:Je,integer:n,numeric:st,real:T,text:a}}const E=Symbol.for("drizzle:SQLiteInlineForeignKeys");class ne extends S{static[o]="SQLiteTable";static Symbol=Object.assign({},S.Symbol,{InlineForeignKeys:E});[S.Symbol.Columns];[E]=[];[S.Symbol.ExtraConfigBuilder]=void 0}function ft(r,e,t,i,u=r){const l=new ne(r,i,u),p=typeof e=="function"?e(pt()):e,c=Object.fromEntries(Object.entries(p).map(([h,s])=>{const m=s;m.setName(h);const g=m.build(l);return l[E].push(...m.buildForeignKeys(g,l)),[h,g]})),d=Object.assign(l,c);return d[S.Symbol.Columns]=c,d[S.Symbol.ExtraConfigColumns]=c,t&&(d[ne.Symbol.ExtraConfigBuilder]=t),d}const b=(r,e,t)=>ft(r,e,t);class ce{constructor(e,t){this.name=e,this.unique=t}static[o]="SQLiteIndexBuilderOn";on(...e){return new gt(this.name,e,this.unique)}}class gt{static[o]="SQLiteIndexBuilder";config;constructor(e,t,i){this.config={name:e,columns:t,unique:i,where:void 0}}where(e){return this.config.where=e,this}build(e){return new ht(this.config,e)}}class ht{static[o]="SQLiteIndex";config;constructor(e,t){this.config={...e,table:t}}}function D(r){return new ce(r,!1)}function yt(r){return new ce(r,!0)}const P=b("users",{id:n("id").primaryKey({autoIncrement:!0}),email:a("email").notNull().unique(),username:a("username").notNull().unique(),fullName:a("full_name"),avatarUrl:a("avatar_url"),role:a("role",{enum:["admin","editor","viewer"]}).notNull().default("viewer"),isActive:n("is_active",{mode:"boolean"}).notNull().default(!0),lastLoginAt:n("last_login_at",{mode:"timestamp"}),createdAt:n("created_at",{mode:"timestamp"}).notNull().default(new Date),updatedAt:n("updated_at",{mode:"timestamp"}).notNull().default(new Date)}),H=b("projects",{id:n("id").primaryKey({autoIncrement:!0}),name:a("name").notNull(),description:a("description"),ownerId:n("owner_id").notNull().references(()=>P.id),isPublic:n("is_public",{mode:"boolean"}).notNull().default(!1),theme:a("theme"),createdAt:n("created_at",{mode:"timestamp"}).notNull().default(new Date),updatedAt:n("updated_at",{mode:"timestamp"}).notNull().default(new Date)}),bt=b("scripts",{id:n("id").primaryKey({autoIncrement:!0}),projectId:n("project_id").notNull().references(()=>H.id),title:a("title").notNull(),slug:a("slug").notNull(),genre:a("genre"),logline:a("logline"),status:a("status",{enum:["draft","revision","final","published"]}).notNull().default("draft"),currentVersion:n("current_version").notNull().default(1),createdAt:n("created_at",{mode:"timestamp"}).notNull().default(new Date),updatedAt:n("updated_at",{mode:"timestamp"}).notNull().default(new Date)}),M=b("characters",{id:n("id").primaryKey({autoIncrement:!0}),projectId:n("project_id").notNull().references(()=>H.id),name:a("name").notNull(),slug:a("slug").notNull(),role:a("role",{enum:["protagonist","antagonist","supporting","background","ensemble"]}).notNull().default("supporting"),bio:a("bio"),description:a("description"),arc:a("arc"),arcType:a("arc_type",{enum:["positive","negative","flat","complex"]}),age:n("age"),gender:a("gender"),voice:a("voice"),traits:a("traits"),motivation:a("motivation"),conflict:a("conflict"),secret:a("secret"),imageUrl:a("image_url"),createdAt:n("created_at",{mode:"timestamp"}).$defaultFn(()=>new Date),updatedAt:n("updated_at",{mode:"timestamp"}).$defaultFn(()=>new Date)});b("character_relationships",{id:n("id").primaryKey({autoIncrement:!0}),characterIdA:n("character_a_id").notNull().references(()=>M.id),characterIdB:n("character_b_id").notNull().references(()=>M.id),relationshipType:a("relationship_type",{enum:["family","romantic","friendship","rivalry","mentor","alliance","conflict","professional","other"]}).notNull(),description:a("description"),strength:n("strength").notNull().default(50),isAntagonistic:n("is_antagonistic",{mode:"boolean"}).notNull().default(!1),createdAt:n("created_at",{mode:"timestamp"}).$defaultFn(()=>new Date),updatedAt:n("updated_at",{mode:"timestamp"}).$defaultFn(()=>new Date)},r=>({uniquePair:yt("character_relationships_unique_pair").on(r.characterIdA,r.characterIdB)}));const St=b("scenes",{id:n("id").primaryKey({autoIncrement:!0}),projectId:n("project_id").notNull().references(()=>H.id),title:a("title").notNull(),content:a("content").notNull().default(""),order:n("order").notNull().default(0),createdAt:n("created_at",{mode:"timestamp"}).$defaultFn(()=>new Date),updatedAt:n("updated_at",{mode:"timestamp"}).$defaultFn(()=>new Date)});b("scene_characters",{id:n("id").primaryKey({autoIncrement:!0}),sceneId:n("scene_id").notNull().references(()=>St.id),characterId:n("character_id").notNull().references(()=>M.id),screenTime:n("screen_time"),dialogueLines:n("dialogue_lines").default(0)});const _t=b("revisions",{id:n("id").primaryKey({autoIncrement:!0}),scriptId:n("script_id").notNull().references(()=>bt.id),versionNumber:n("version_number").notNull(),branchName:a("branch_name").notNull().default("main"),parentRevisionId:n("parent_revision_id"),title:a("title").notNull(),summary:a("summary"),content:a("content").notNull(),authorId:n("author_id").notNull().references(()=>P.id),status:a("status",{enum:["draft","pending_review","accepted","rejected"]}).notNull().default("draft"),reviewedById:n("reviewed_by_id").references(()=>P.id),reviewedAt:n("reviewed_at",{mode:"timestamp"}),createdAt:n("created_at",{mode:"timestamp"}).notNull().$defaultFn(()=>new Date),updatedAt:n("updated_at",{mode:"timestamp"}).notNull().$defaultFn(()=>new Date)},r=>({scriptVersionIdx:D("revisions_script_version_idx").on(r.scriptId,r.versionNumber),scriptBranchIdx:D("revisions_script_branch_idx").on(r.scriptId,r.branchName),authorIdx:D("revisions_author_idx").on(r.authorId)}));b("revision_changes",{id:n("id").primaryKey({autoIncrement:!0}),revisionId:n("revision_id").notNull().references(()=>_t.id),changeType:a("change_type",{enum:["addition","deletion","modification"]}).notNull(),elementType:a("element_type"),oldContent:a("old_content"),newContent:a("new_content"),sceneNumber:n("scene_number"),lineNumber:n("line_number"),pageNumber:n("page_number"),createdAt:n("created_at",{mode:"timestamp"}).notNull().$defaultFn(()=>new Date)},r=>({revisionIdx:D("revision_changes_revision_idx").on(r.revisionId),changeTypeIdx:D("revision_changes_type_idx").on(r.changeType)}));b("kpi_snapshots",{id:n("id").primaryKey({autoIncrement:!0}),kpiKey:a("kpi_key").notNull(),kpiValue:T("kpi_value").notNull(),periodStart:n("period_start",{mode:"timestamp"}).notNull(),periodEnd:n("period_end",{mode:"timestamp"}).notNull(),metadata:a("metadata"),createdAt:n("created_at",{mode:"timestamp"}).notNull().default(new Date)});const vt=b("alert_rules",{id:n("id").primaryKey({autoIncrement:!0}),name:a("name").notNull(),kpiKey:a("kpi_key").notNull(),condition:a("condition",{enum:["above","below","equals","increasing","decreasing"]}).notNull(),threshold:T("threshold").notNull(),severity:a("severity",{enum:["low","medium","high","critical"]}).notNull().default("medium"),channelId:a("channel_id"),isActive:n("is_active",{mode:"boolean"}).notNull().default(!0),cooldownMinutes:n("cooldown_minutes").notNull().default(60),createdAt:n("created_at",{mode:"timestamp"}).notNull().default(new Date),updatedAt:n("updated_at",{mode:"timestamp"}).notNull().default(new Date)});b("alerts",{id:n("id").primaryKey({autoIncrement:!0}),ruleId:n("rule_id").notNull().references(()=>vt.id),kpiKey:a("kpi_key").notNull(),kpiValue:T("kpi_value").notNull(),threshold:T("threshold").notNull(),severity:a("severity",{enum:["low","medium","high","critical"]}).notNull(),message:a("message").notNull(),wasSent:n("was_sent",{mode:"boolean"}).notNull().default(!1),sentAt:n("sent_at",{mode:"timestamp"}),acknowledgedBy:n("acknowledged_by"),acknowledgedAt:n("acknowledged_at",{mode:"timestamp"}),createdAt:n("created_at",{mode:"timestamp"}).notNull().default(new Date)});b("scheduled_reports",{id:n("id").primaryKey({autoIncrement:!0}),name:a("name").notNull(),reportType:a("report_type",{enum:["weekly_kpi","monthly_kpi","cohort_analysis","nps_summary","custom"]}).notNull(),schedule:a("schedule").notNull(),recipients:a("recipients").notNull(),format:a("format",{enum:["slack","email","both"]}).notNull().default("slack"),isActive:n("is_active",{mode:"boolean"}).notNull().default(!0),lastRunAt:n("last_run_at",{mode:"timestamp"}),nextRunAt:n("next_run_at",{mode:"timestamp"}),metadata:a("metadata"),createdAt:n("created_at",{mode:"timestamp"}).notNull().default(new Date),updatedAt:n("updated_at",{mode:"timestamp"}).notNull().default(new Date)});b("nps_responses",{id:n("id").primaryKey({autoIncrement:!0}),userId:n("user_id").references(()=>P.id),score:n("score").notNull(),category:a("category",{enum:["detractor","passive","promoter"]}).notNull(),feedback:a("feedback"),surveyId:a("survey_id"),respondentEmail:a("respondent_email"),createdAt:n("created_at",{mode:"timestamp"}).notNull().default(new Date)});const Nt=b("cohorts",{id:n("id").primaryKey({autoIncrement:!0}),name:a("name").notNull(),definition:a("definition").notNull(),periodStart:n("period_start",{mode:"timestamp"}).notNull(),periodEnd:n("period_end",{mode:"timestamp"}),size:n("size").notNull().default(0),retentionData:a("retention_data"),metadata:a("metadata"),createdAt:n("created_at",{mode:"timestamp"}).notNull().default(new Date),updatedAt:n("updated_at",{mode:"timestamp"}).notNull().default(new Date)});b("cohort_members",{id:n("id").primaryKey({autoIncrement:!0}),cohortId:n("cohort_id").notNull().references(()=>Nt.id),userId:n("user_id").notNull(),joinedAt:n("joined_at",{mode:"timestamp"}).notNull().default(new Date)});const wt=b("waitlist_signups",{id:n("id").primaryKey({autoIncrement:!0}),email:a("email").notNull().unique(),name:a("name"),source:a("source").notNull().default("organic"),status:a("status").notNull().default("waitlist"),metadata:a("metadata"),createdAt:n("created_at",{mode:"timestamp"}).notNull().default(new Date),updatedAt:n("updated_at",{mode:"timestamp"}).notNull().default(new Date)});b("waitlist_events",{id:n("id").primaryKey({autoIncrement:!0}),signupId:n("signup_id").notNull().references(()=>wt.id),eventType:a("event_type").notNull(),eventData:a("event_data"),createdAt:n("created_at",{mode:"timestamp"}).notNull().default(new Date)});const It={mau:{warning:1e3,critical:500,direction:"higher"},paying_users:{warning:100,critical:50,direction:"higher"},mrr:{warning:5e3,critical:2e3,direction:"higher"},conversion_rate:{warning:2,critical:1,direction:"higher"},churn_rate:{warning:5,critical:3,direction:"lower"},cac:{warning:12,critical:15,direction:"lower"},ltv:{warning:100,critical:80,direction:"higher"},nps:{warning:40,critical:20,direction:"higher"},viral_coefficient:{warning:.3,critical:.1,direction:"higher"}};var xt=I('
Unified KPI Report
Cross-tool KPI summary template
KPI Thresholds Reference
All tracked KPIs with their target thresholds and alert levels. This template is designed for weekly/monthly reporting across all analytics tools.
KPI
Category
Warning Threshold
Critical Threshold
Direction
Reporting Schedule
Weekly Report: Auto-generated every Monday at 9:00 AM
Monthly Report: Auto-generated on the 1st of each month
Alert Thresholds: Real-time notifications via Slack when KPIs breach warning/critical levels