@@ -52,7 +52,8 @@ const SEED_DATA_TEMPLATE = readTemplateSync("init/dataconnect/seed_data.gql");
5252
5353export interface RequiredInfo {
5454 // The GA analytics metric to track how developers go through `init dataconnect`.
55- analyticsFlow : string ;
55+ source : "mcp_init" | "init" | "init_sdk" ;
56+ flow : string ;
5657 appDescription : string ;
5758 serviceId : string ;
5859 locationId : string ;
@@ -99,7 +100,8 @@ const templateServiceInfo: ServiceGQL = {
99100// logic should live here, and _no_ actuation logic should live here.
100101export async function askQuestions ( setup : Setup ) : Promise < void > {
101102 const info : RequiredInfo = {
102- analyticsFlow : "cli" ,
103+ source : "init" ,
104+ flow : "" ,
103105 appDescription : "" ,
104106 serviceId : "" ,
105107 locationId : "" ,
@@ -166,20 +168,28 @@ export async function actuate(setup: Setup, config: Config, options: any): Promi
166168 info . locationId = info . locationId || FDC_DEFAULT_REGION ;
167169 info . cloudSqlDatabase = info . cloudSqlDatabase || `fdcdb` ;
168170
171+ const startTime = Date . now ( ) ;
169172 try {
170173 await actuateWithInfo ( setup , config , info , options ) ;
171174 await sdk . actuate ( setup , config ) ;
172175 } finally {
173- void trackGA4 ( "dataconnect_init" , {
174- flow : info . analyticsFlow ,
175- project_status : setup . projectId
176- ? setup . isBillingEnabled
177- ? info . shouldProvisionCSQL
178- ? "blaze_provisioned_csql"
179- : "blaze"
180- : "spark"
181- : "missing" ,
182- } ) ;
176+ const sdkInfo = setup . featureInfo ?. dataconnectSdk ;
177+ void trackGA4 (
178+ "dataconnect_init" ,
179+ {
180+ source : info . source ,
181+ flow : info . flow . substring ( 1 ) , // Trim the leading `_`
182+ project_status : setup . projectId
183+ ? setup . isBillingEnabled
184+ ? info . shouldProvisionCSQL
185+ ? "blaze_provisioned_csql"
186+ : "blaze"
187+ : "spark"
188+ : "missing" ,
189+ ...( sdkInfo ? sdk . initAppCounters ( sdkInfo ) : { } ) ,
190+ } ,
191+ Date . now ( ) - startTime ,
192+ ) ;
183193 }
184194
185195 if ( info . appDescription ) {
@@ -206,7 +216,7 @@ async function actuateWithInfo(
206216 const projectId = setup . projectId ;
207217 if ( ! projectId ) {
208218 // If no project is present, just save the template files.
209- info . analyticsFlow += "_save_template" ;
219+ info . flow += "_save_template" ;
210220 return await writeFiles ( config , info , templateServiceInfo , options ) ;
211221 }
212222
@@ -220,7 +230,7 @@ async function actuateWithInfo(
220230 instanceId : info . cloudSqlInstanceId ,
221231 databaseId : info . cloudSqlDatabase ,
222232 requireGoogleMlIntegration : false ,
223- source : info . analyticsFlow . startsWith ( "mcp" ) ? "mcp_init" : "init" ,
233+ source : info . source ,
224234 } ) ;
225235 }
226236
@@ -233,11 +243,11 @@ async function actuateWithInfo(
233243 }
234244 if ( info . serviceGql ) {
235245 // Save the downloaded service from the backend.
236- info . analyticsFlow += "_save_downloaded" ;
246+ info . flow += "_save_downloaded" ;
237247 return await writeFiles ( config , info , info . serviceGql , options ) ;
238248 }
239249 // Use the static template if it starts from scratch or the existing service has no GQL source.
240- info . analyticsFlow += "_save_template" ;
250+ info . flow += "_save_template" ;
241251 return await writeFiles ( config , info , templateServiceInfo , options ) ;
242252 }
243253 const serviceAlreadyExists = ! ( await createService ( projectId , info . locationId , info . serviceId ) ) ;
@@ -259,7 +269,7 @@ async function actuateWithInfo(
259269 "dataconnect" ,
260270 `Data Connect Service ${ serviceName } already exists. Skip saving them...` ,
261271 ) ;
262- info . analyticsFlow += "_save_gemini_service_already_exists" ;
272+ info . flow += "_save_gemini_service_already_exists" ;
263273 return await writeFiles ( config , info , { schemaGql : schemaFiles , connectors : [ ] } , options ) ;
264274 }
265275
@@ -301,7 +311,7 @@ async function actuateWithInfo(
301311 ] ,
302312 } ,
303313 ] ;
304- info . analyticsFlow += "_save_gemini" ;
314+ info . flow += "_save_gemini" ;
305315 await writeFiles (
306316 config ,
307317 info ,
@@ -312,7 +322,7 @@ async function actuateWithInfo(
312322 logLabeledError ( "dataconnect" , `Operation Generation failed...` ) ;
313323 // GiF generate operation API has stability concerns.
314324 // Fallback to save only the generated schema.
315- info . analyticsFlow += "_save_gemini_operation_error" ;
325+ info . flow += "_save_gemini_operation_error" ;
316326 await writeFiles ( config , info , { schemaGql : schemaFiles , connectors : [ ] } , options ) ;
317327 throw err ;
318328 }
@@ -492,11 +502,11 @@ async function promptForExistingServices(setup: Setup, info: RequiredInfo): Prom
492502 if ( ! choice ) {
493503 const existingServiceIds = existingServices . map ( ( s ) => s . name . split ( "/" ) . pop ( ) ! ) ;
494504 info . serviceId = newUniqueId ( defaultServiceId ( ) , existingServiceIds ) ;
495- info . analyticsFlow += "_pick_new_service" ;
505+ info . flow += "_pick_new_service" ;
496506 return ;
497507 }
498508 // Choose to use an existing service.
499- info . analyticsFlow += "_pick_existing_service" ;
509+ info . flow += "_pick_existing_service" ;
500510 const serviceName = parseServiceName ( choice . name ) ;
501511 info . serviceId = serviceName . serviceId ;
502512 info . locationId = serviceName . location ;
@@ -618,11 +628,11 @@ async function promptForCloudSQL(setup: Setup, info: RequiredInfo): Promise<void
618628 choices,
619629 } ) ;
620630 if ( info . cloudSqlInstanceId !== "" ) {
621- info . analyticsFlow += "_pick_existing_csql" ;
631+ info . flow += "_pick_existing_csql" ;
622632 // Infer location if a CloudSQL instance is chosen.
623633 info . locationId = choices . find ( ( c ) => c . value === info . cloudSqlInstanceId ) ! . location ;
624634 } else {
625- info . analyticsFlow += "_pick_new_csql" ;
635+ info . flow += "_pick_new_csql" ;
626636 info . cloudSqlInstanceId = await input ( {
627637 message : `What ID would you like to use for your new CloudSQL instance?` ,
628638 default : newUniqueId (
0 commit comments