@yoryoboy/bi-mcp 1.6.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +87 -87
- package/bin/bi-mcp.js +9 -9
- package/dist/.tsbuildinfo +1 -1
- package/dist/index.js +14 -3
- package/dist/index.js.map +2 -2
- package/dist/mcp-use.json +2 -2
- package/dist/public/icon.svg +6 -6
- package/dist/scripts/_helpers.js.map +1 -1
- package/dist/scripts/admin-profile-delete.js.map +1 -1
- package/dist/scripts/admin-profile-list.js.map +1 -1
- package/dist/scripts/admin-profile-upsert.js.map +1 -1
- package/dist/scripts/admin-vtex-list.js.map +1 -1
- package/dist/scripts/admin-vtex-upsert.js.map +1 -1
- package/dist/scripts/admin-vtex-validate.js.map +1 -1
- package/dist/scripts/run-migrations.js.map +1 -1
- package/dist/scripts/test-db-connection.js.map +1 -1
- package/dist/src/analytics/ga4-channel-groups.js.map +1 -1
- package/dist/src/analytics/ga4-report-utils.js.map +1 -1
- package/dist/src/config/benchmarks.js.map +1 -1
- package/dist/src/config/google-store.js.map +1 -1
- package/dist/src/config/google.js.map +1 -1
- package/dist/src/config/mercadolibre-profile-store.js.map +1 -1
- package/dist/src/config/mercadolibre.js.map +1 -1
- package/dist/src/config/meta.js.map +1 -1
- package/dist/src/config/profile-store.js.map +1 -1
- package/dist/src/config/vtex-crypto.js.map +1 -1
- package/dist/src/config/vtex-profile-store.js.map +1 -1
- package/dist/src/config/vtex.js.map +1 -1
- package/dist/src/db/client.js.map +1 -1
- package/dist/src/google-ads/report-utils.js +78 -0
- package/dist/src/google-ads/report-utils.js.map +7 -0
- package/dist/src/meta/meta-utils.js.map +1 -1
- package/dist/src/prompts/reporte-ventas.js.map +1 -1
- package/dist/src/search-console/search-console-utils.js +275 -0
- package/dist/src/search-console/search-console-utils.js.map +7 -0
- package/dist/src/services/analytics/ga4-client.js.map +1 -1
- package/dist/src/services/analytics/oauth.js.map +1 -1
- package/dist/src/services/google-ads/google-ads-client.js.map +1 -1
- package/dist/src/services/mercadolibre/mercadolibre-api.js.map +1 -1
- package/dist/src/services/mercadolibre/mercadolibre-items.js +29 -2
- package/dist/src/services/mercadolibre/mercadolibre-items.js.map +2 -2
- package/dist/src/services/mercadolibre/mercadolibre-orders.js.map +1 -1
- package/dist/src/services/mercadolibre/mercadolibre-questions.js.map +1 -1
- package/dist/src/services/meta/meta-ads.js.map +1 -1
- package/dist/src/services/meta/meta-api.js.map +1 -1
- package/dist/src/services/search-console/search-console-client.js.map +1 -1
- package/dist/src/services/search-console/search-console-utils.js.map +1 -1
- package/dist/src/services/vtex/vtex-api.js.map +1 -1
- package/dist/src/services/vtex/vtex-catalog-write.js.map +1 -1
- package/dist/src/services/vtex/vtex-catalog.js.map +1 -1
- package/dist/src/services/vtex/vtex-logistics.js.map +1 -1
- package/dist/src/services/vtex/vtex-orders-write.js.map +1 -1
- package/dist/src/services/vtex/vtex-orders.js.map +1 -1
- package/dist/src/services/vtex/vtex-pricing-write.js.map +1 -1
- package/dist/src/services/vtex/vtex-pricing.js.map +1 -1
- package/dist/src/services/vtex/vtex-write.js.map +1 -1
- package/dist/src/tools/analytics/attribution-gaps.js.map +1 -1
- package/dist/src/tools/analytics/channel-mix.js.map +1 -1
- package/dist/src/tools/analytics/ecommerce-tracking-health.js.map +1 -1
- package/dist/src/tools/analytics/engagement-overview.js.map +1 -1
- package/dist/src/tools/analytics/index.js.map +1 -1
- package/dist/src/tools/analytics/list-accessible-properties.js.map +1 -1
- package/dist/src/tools/analytics/property-info.js.map +1 -1
- package/dist/src/tools/analytics/revenue-by-channel.js.map +1 -1
- package/dist/src/tools/analytics/revenue-overview.js.map +1 -1
- package/dist/src/tools/analytics/revenue-trend.js.map +1 -1
- package/dist/src/tools/analytics/source-medium-breakdown.js.map +1 -1
- package/dist/src/tools/analytics/top-landing-pages.js.map +1 -1
- package/dist/src/tools/config/check-database-connection.js.map +1 -1
- package/dist/src/tools/config/index.js.map +1 -1
- package/dist/src/tools/config/list-profiles.js.map +1 -1
- package/dist/src/tools/google-ads/account-overview.js.map +1 -1
- package/dist/src/tools/google-ads/account-risks.js.map +1 -1
- package/dist/src/tools/google-ads/break-even-analysis.js.map +1 -1
- package/dist/src/tools/google-ads/campaign-performance.js.map +1 -1
- package/dist/src/tools/google-ads/channel-mix.js.map +1 -1
- package/dist/src/tools/google-ads/compare-accounts.js.map +1 -1
- package/dist/src/tools/google-ads/customer-clients.js.map +1 -1
- package/dist/src/tools/google-ads/customer-info.js.map +1 -1
- package/dist/src/tools/google-ads/index.js.map +1 -1
- package/dist/src/tools/google-ads/scaling-health.js.map +1 -1
- package/dist/src/tools/google-ads/search-terms-summary.js.map +1 -1
- package/dist/src/tools/google-ads/time-series.js.map +1 -1
- package/dist/src/tools/index.js.map +1 -1
- package/dist/src/tools/mercadolibre/answer-question.js.map +1 -1
- package/dist/src/tools/mercadolibre/create-item.js.map +1 -1
- package/dist/src/tools/mercadolibre/estimate-listing-fee.js +4 -17
- package/dist/src/tools/mercadolibre/estimate-listing-fee.js.map +2 -2
- package/dist/src/tools/mercadolibre/get-account-context.js.map +1 -1
- package/dist/src/tools/mercadolibre/get-category-requirements.js.map +1 -1
- package/dist/src/tools/mercadolibre/get-item-details.js.map +1 -1
- package/dist/src/tools/mercadolibre/get-item-visits.js.map +1 -1
- package/dist/src/tools/mercadolibre/get-listing-quality.js.map +1 -1
- package/dist/src/tools/mercadolibre/get-order-details.js.map +1 -1
- package/dist/src/tools/mercadolibre/get-orders-summary.js +366 -28
- package/dist/src/tools/mercadolibre/get-orders-summary.js.map +2 -2
- package/dist/src/tools/mercadolibre/get-sales-by-item.js.map +1 -1
- package/dist/src/tools/mercadolibre/get-sales-trend.js.map +1 -1
- package/dist/src/tools/mercadolibre/get-shipping-summary.js.map +1 -1
- package/dist/src/tools/mercadolibre/get-site-categories-and-listing-types.js +50 -0
- package/dist/src/tools/mercadolibre/get-site-categories-and-listing-types.js.map +7 -0
- package/dist/src/tools/mercadolibre/get-store-performance.js.map +1 -1
- package/dist/src/tools/mercadolibre/helpers.js.map +1 -1
- package/dist/src/tools/mercadolibre/index.js +1 -0
- package/dist/src/tools/mercadolibre/index.js.map +2 -2
- package/dist/src/tools/mercadolibre/pause-or-reactivate-item.js.map +1 -1
- package/dist/src/tools/mercadolibre/predict-category.js.map +1 -1
- package/dist/src/tools/mercadolibre/profile-resolution.js.map +1 -1
- package/dist/src/tools/mercadolibre/search-items.js +207 -52
- package/dist/src/tools/mercadolibre/search-items.js.map +2 -2
- package/dist/src/tools/mercadolibre/search-questions.js.map +1 -1
- package/dist/src/tools/mercadolibre/update-item-basic-fields.js.map +1 -1
- package/dist/src/tools/mercadolibre/update-item-description.js.map +1 -1
- package/dist/src/tools/mercadolibre/update-item-pictures.js.map +1 -1
- package/dist/src/tools/mercadolibre/validate-connection.js.map +1 -1
- package/dist/src/tools/mercadolibre/write-helpers.js.map +1 -1
- package/dist/src/tools/meta/account-overview.js.map +1 -1
- package/dist/src/tools/meta/ad-account-info.js.map +1 -1
- package/dist/src/tools/meta/ads-performance.js.map +1 -1
- package/dist/src/tools/meta/campaign-performance.js.map +1 -1
- package/dist/src/tools/meta/index.js.map +1 -1
- package/dist/src/tools/meta/list-accessible-ad-accounts.js.map +1 -1
- package/dist/src/tools/meta/list-accessible-businesses.js.map +1 -1
- package/dist/src/tools/meta/placement-mix.js.map +1 -1
- package/dist/src/tools/meta/time-series.js.map +1 -1
- package/dist/src/tools/search-console/country-breakdown.js.map +1 -1
- package/dist/src/tools/search-console/device-breakdown.js.map +1 -1
- package/dist/src/tools/search-console/high-impression-low-click-queries.js.map +1 -1
- package/dist/src/tools/search-console/index.js.map +1 -1
- package/dist/src/tools/search-console/list-accessible-sites.js.map +1 -1
- package/dist/src/tools/search-console/low-ctr-opportunities.js.map +1 -1
- package/dist/src/tools/search-console/page-performance.js.map +1 -1
- package/dist/src/tools/search-console/product-demand-low-capture-queries.js.map +1 -1
- package/dist/src/tools/search-console/query-page-matrix.js.map +1 -1
- package/dist/src/tools/search-console/query-performance.js.map +1 -1
- package/dist/src/tools/search-console/quick-win-opportunities.js.map +1 -1
- package/dist/src/tools/search-console/rising-non-brand-queries.js.map +1 -1
- package/dist/src/tools/search-console/search-performance.js.map +1 -1
- package/dist/src/tools/search-console/site-context.js.map +1 -1
- package/dist/src/tools/search-console/visibility-declines.js.map +1 -1
- package/dist/src/tools/vtex/activate-sku.js.map +1 -1
- package/dist/src/tools/vtex/add-order-tracking.js.map +1 -1
- package/dist/src/tools/vtex/associate-specification.js.map +1 -1
- package/dist/src/tools/vtex/attach-catalog-image.js.map +1 -1
- package/dist/src/tools/vtex/cancel-order.js.map +1 -1
- package/dist/src/tools/vtex/computed-price.js.map +1 -1
- package/dist/src/tools/vtex/create-brand.js.map +1 -1
- package/dist/src/tools/vtex/create-category.js.map +1 -1
- package/dist/src/tools/vtex/create-product-with-sku.js.map +1 -1
- package/dist/src/tools/vtex/create-product.js.map +1 -1
- package/dist/src/tools/vtex/create-sku.js.map +1 -1
- package/dist/src/tools/vtex/create-specification-value.js.map +1 -1
- package/dist/src/tools/vtex/create-specification.js.map +1 -1
- package/dist/src/tools/vtex/deactivate-sku.js.map +1 -1
- package/dist/src/tools/vtex/delete-fixed-price.js.map +1 -1
- package/dist/src/tools/vtex/index.js.map +1 -1
- package/dist/src/tools/vtex/inventory-check.js.map +1 -1
- package/dist/src/tools/vtex/invoice-order.js.map +1 -1
- package/dist/src/tools/vtex/order-details.js.map +1 -1
- package/dist/src/tools/vtex/orders-summary.js.map +1 -1
- package/dist/src/tools/vtex/product-offers.js.map +1 -1
- package/dist/src/tools/vtex/profile-resolution.js.map +1 -1
- package/dist/src/tools/vtex/sku-offers.js.map +1 -1
- package/dist/src/tools/vtex/sku-price.js.map +1 -1
- package/dist/src/tools/vtex/toggle-unlimited-quantity.js.map +1 -1
- package/dist/src/tools/vtex/update-inventory.js.map +1 -1
- package/dist/src/tools/vtex/update-lead-time.js.map +1 -1
- package/dist/src/tools/vtex/update-product-basic-fields.js.map +1 -1
- package/dist/src/tools/vtex/update-sku-basic-fields.js.map +1 -1
- package/dist/src/tools/vtex/update-sku-price.js.map +1 -1
- package/dist/src/tools/vtex/upsert-fixed-price.js.map +1 -1
- package/dist/src/tools/vtex/warehouse-inventory.js.map +1 -1
- package/dist/src/tools/vtex/write-helpers.js.map +1 -1
- package/dist/src/utils/case-conversion.js.map +1 -1
- package/dist/src/utils/currency.js.map +1 -1
- package/dist/src/utils/format-order-details.js.map +1 -1
- package/dist/src/utils/google-ads.js.map +1 -1
- package/dist/src/utils/money.js.map +1 -1
- package/dist/src/utils/order-status.js.map +1 -1
- package/dist/src/utils/pagination.js.map +1 -1
- package/dist/src/utils/strip-payload.js.map +1 -1
- package/dist/src/utils/type-guards.js.map +1 -1
- package/package.json +1 -1
- package/public/icon.svg +6 -6
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/services/vtex/vtex-write.ts"],
|
|
4
|
-
"sourcesContent": ["export type VtexWriteRiskLevel = \"low\" | \"high\";\
|
|
4
|
+
"sourcesContent": ["export type VtexWriteRiskLevel = \"low\" | \"high\";\n\nexport type VtexWriteErrorCode =\n | \"EXPLICIT_CONFIRMATION_REQUIRED\"\n | \"INVALID_ORDER_STATE\"\n | \"RESOURCE_NOT_FOUND\"\n | \"INVALID_OPERATION\";\n\nexport interface VtexWriteSummary extends Record<string, unknown> {\n before?: Record<string, unknown> | null;\n after?: Record<string, unknown> | null;\n}\n\nexport interface VtexWriteResult extends Record<string, unknown> {\n success: boolean;\n profile_id?: string;\n operation: string;\n resource_id?: string;\n risk_level: VtexWriteRiskLevel;\n confirmed?: boolean;\n message: string;\n summary?: VtexWriteSummary;\n confirmation_note?: string;\n details?: Record<string, unknown>;\n}\n\nexport interface VtexWriteErrorResult extends Record<string, unknown> {\n success: false;\n error_code: VtexWriteErrorCode;\n message: string;\n operation: string;\n risk_level: VtexWriteRiskLevel;\n details?: Record<string, unknown>;\n}\n\nexport class VtexOperationError extends Error {\n constructor(\n message: string,\n public readonly code: VtexWriteErrorCode,\n public readonly details?: Record<string, unknown>\n ) {\n super(message);\n this.name = \"VtexOperationError\";\n }\n}\n\nexport function buildConfirmationRequiredResult(\n operation: string,\n details?: Record<string, unknown>\n): VtexWriteErrorResult {\n return {\n success: false,\n error_code: \"EXPLICIT_CONFIRMATION_REQUIRED\",\n message: \"This VTEX operation is high-risk and requires explicit user confirmation before execution.\",\n operation,\n risk_level: \"high\",\n details,\n };\n}\n\nexport function buildWriteSuccessResult(params: {\n profileId: string;\n operation: string;\n resourceId?: string;\n riskLevel: VtexWriteRiskLevel;\n confirmed?: boolean;\n message: string;\n summary?: VtexWriteSummary;\n confirmationNote?: string;\n details?: Record<string, unknown>;\n}): VtexWriteResult {\n return {\n success: true,\n profile_id: params.profileId,\n operation: params.operation,\n resource_id: params.resourceId,\n risk_level: params.riskLevel,\n confirmed: params.confirmed,\n message: params.message,\n summary: params.summary,\n confirmation_note: params.confirmationNote,\n details: params.details,\n };\n}\n"],
|
|
5
5
|
"mappings": "AAmCO,MAAM,2BAA2B,MAAM;AAAA,EAC5C,YACE,SACgB,MACA,SAChB;AACA,UAAM,OAAO;AAHG;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,SAAS,gCACd,WACA,SACsB;AACtB,SAAO;AAAA,IACL,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,SAAS;AAAA,IACT;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,EACF;AACF;AAEO,SAAS,wBAAwB,QAUpB;AAClB,SAAO;AAAA,IACL,SAAS;AAAA,IACT,YAAY,OAAO;AAAA,IACnB,WAAW,OAAO;AAAA,IAClB,aAAa,OAAO;AAAA,IACpB,YAAY,OAAO;AAAA,IACnB,WAAW,OAAO;AAAA,IAClB,SAAS,OAAO;AAAA,IAChB,SAAS,OAAO;AAAA,IAChB,mBAAmB,OAAO;AAAA,IAC1B,SAAS,OAAO;AAAA,EAClB;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/analytics/attribution-gaps.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport {\n detectSeverity,\n extractQuotaSnapshot,\n getDimensionValue,\n getMetricValueByName,\n isProblematicAttributionValue,\n resolveGa4PropertyId,\n round,\n toPercent,\n} from \"../../analytics/ga4-report-utils.js\";\nimport { runReport } from \"../../services/analytics/ga4-client.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nconst dateRegex = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nexport const attributionGapsSchema = z.object({\n startDate: z.string().regex(dateRegex).describe(\"Start date in YYYY-MM-DD format\"),\n endDate: z.string().regex(dateRegex).describe(\"End date in YYYY-MM-DD format\"),\n propertyId: z.string().optional().describe(\"GA4 property ID. If omitted, resolves profileId mapping first and then GA4_PROPERTY_ID.\"),\n profileId: z.string().optional().describe(\"Optional business profile ID used to resolve the mapped GA4 property.\"),\n limit: z.number().int().min(10).max(100).optional().describe(\"Maximum source / medium rows to inspect\"),\n});\n\nexport async function attributionGapsHandler(params: z.infer<typeof attributionGapsSchema>) {\n try {\n const propertyId = await resolveGa4PropertyId(params.propertyId, params.profileId);\n const limit = params.limit ?? 50;\n\n const [channelReport, sourceMediumReport, totalReport] = await Promise.all([\n runReport(propertyId, {\n dateRanges: [{ startDate: params.startDate, endDate: params.endDate }],\n dimensions: [{ name: \"sessionDefaultChannelGroup\" }],\n metrics: [{ name: \"sessions\" }, { name: \"totalUsers\" }],\n }),\n runReport(propertyId, {\n dateRanges: [{ startDate: params.startDate, endDate: params.endDate }],\n dimensions: [{ name: \"sessionSourceMedium\" }],\n metrics: [{ name: \"sessions\" }, { name: \"totalUsers\" }],\n orderBys: [{ metric: { metricName: \"sessions\" }, desc: true }],\n limit,\n returnPropertyQuota: true,\n }),\n runReport(propertyId, {\n dateRanges: [{ startDate: params.startDate, endDate: params.endDate }],\n metrics: [{ name: \"sessions\" }],\n }),\n ]);\n\n const totalSessions = getMetricValueByName(\n totalReport.rows?.[0] ?? {},\n totalReport.metricHeaders,\n \"sessions\"\n );\n\n const unassignedChannel = (channelReport.rows ?? []).find(\n (row) => getDimensionValue(row) === \"Unassigned\"\n );\n const unassignedSessions = getMetricValueByName(\n unassignedChannel ?? {},\n channelReport.metricHeaders,\n \"sessions\"\n );\n\n const problematicSourceMediumRows = (sourceMediumReport.rows ?? [])\n .filter((row) => isProblematicAttributionValue(getDimensionValue(row)))\n .map((row) => {\n const sessions = getMetricValueByName(row, sourceMediumReport.metricHeaders, \"sessions\");\n const users = getMetricValueByName(row, sourceMediumReport.metricHeaders, \"totalUsers\");\n\n return {\n source_medium: getDimensionValue(row),\n sessions,\n users,\n session_share_percent: round(toPercent(sessions, totalSessions)),\n };\n });\n\n const problematicSourceMediumSessions = problematicSourceMediumRows.reduce(\n (total, row) => total + row.sessions,\n 0\n );\n const unassignedSharePercent = round(toPercent(unassignedSessions, totalSessions));\n const problematicSourceMediumSharePercent = round(\n toPercent(problematicSourceMediumSessions, totalSessions)\n );\n\n return object(\n stripNulls({\n property_id: propertyId,\n date_range: {\n start_date: params.startDate,\n end_date: params.endDate,\n },\n overview: {\n total_sessions: totalSessions,\n attribution_warning: \"Las se\u00F1ales se reportan por separado para evitar doble conteo entre dimensiones distintas de GA4.\",\n },\n unassigned_channel_group: {\n sessions: unassignedSessions,\n session_share_percent: unassignedSharePercent,\n severity: detectSeverity(unassignedSharePercent),\n },\n problematic_source_medium: {\n sessions: problematicSourceMediumSessions,\n session_share_percent: problematicSourceMediumSharePercent,\n severity: detectSeverity(problematicSourceMediumSharePercent),\n },\n problematic_source_mediums: problematicSourceMediumRows,\n quota: extractQuotaSnapshot(sourceMediumReport),\n })\n );\n } catch (err) {\n return error(err instanceof Error ? err.message : \"Failed to detect GA4 attribution gaps\");\n }\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/analytics/channel-mix.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport {\n extractQuotaSnapshot,\n getDimensionValue,\n getMetricValueByName,\n resolveGa4PropertyId,\n round,\n sumMetricValues,\n toPercent,\n} from \"../../analytics/ga4-report-utils.js\";\nimport { isPaidDefaultChannelGroup } from \"../../analytics/ga4-channel-groups.js\";\nimport { runReport } from \"../../services/analytics/ga4-client.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nconst dateRegex = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nexport const channelMixSchema = z.object({\n startDate: z.string().regex(dateRegex).describe(\"Start date in YYYY-MM-DD format\"),\n endDate: z.string().regex(dateRegex).describe(\"End date in YYYY-MM-DD format\"),\n propertyId: z.string().optional().describe(\"GA4 property ID. If omitted, resolves profileId mapping first and then GA4_PROPERTY_ID.\"),\n profileId: z.string().optional().describe(\"Optional business profile ID used to resolve the mapped GA4 property.\"),\n});\n\nexport async function channelMixHandler(params: z.infer<typeof channelMixSchema>) {\n try {\n const propertyId = await resolveGa4PropertyId(params.propertyId, params.profileId);\n\n const report = await runReport(propertyId, {\n dateRanges: [{ startDate: params.startDate, endDate: params.endDate }],\n dimensions: [{ name: \"sessionDefaultChannelGroup\" }],\n metrics: [{ name: \"sessions\" }, { name: \"totalUsers\" }],\n orderBys: [{ metric: { metricName: \"sessions\" }, desc: true }],\n returnPropertyQuota: true,\n });\n\n const totalSessions = sumMetricValues(report.rows, report.metricHeaders, \"sessions\");\n const totalUsers = sumMetricValues(report.rows, report.metricHeaders, \"totalUsers\");\n\n const channels = (report.rows ?? []).map((row) => {\n const sessions = getMetricValueByName(row, report.metricHeaders, \"sessions\");\n const users = getMetricValueByName(row, report.metricHeaders, \"totalUsers\");\n\n return {\n channel: getDimensionValue(row),\n sessions,\n users,\n session_share_percent: round(toPercent(sessions, totalSessions)),\n user_share_percent: round(toPercent(users, totalUsers)),\n };\n });\n\n const paidSessions = channels\n .filter((channel) => isPaidDefaultChannelGroup(channel.channel))\n .reduce((total, channel) => total + channel.sessions, 0);\n const organicSessions = channels\n .filter((channel) => channel.channel.startsWith(\"Organic\"))\n .reduce((total, channel) => total + channel.sessions, 0);\n const directSessions = channels\n .filter((channel) => channel.channel === \"Direct\")\n .reduce((total, channel) => total + channel.sessions, 0);\n\n return object(\n stripNulls({\n property_id: propertyId,\n date_range: {\n start_date: params.startDate,\n end_date: params.endDate,\n },\n overview: {\n total_sessions: totalSessions,\n total_users: totalUsers,\n top_channel: channels[0]?.channel,\n paid_session_share_percent: round(toPercent(paidSessions, totalSessions)),\n organic_session_share_percent: round(toPercent(organicSessions, totalSessions)),\n direct_session_share_percent: round(toPercent(directSessions, totalSessions)),\n },\n channels,\n quota: extractQuotaSnapshot(report),\n })\n );\n } catch (err) {\n return error(err instanceof Error ? err.message : \"Failed to fetch GA4 channel mix\");\n }\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/analytics/ecommerce-tracking-health.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport {\n extractQuotaSnapshot,\n getMetricValueByName,\n resolveGa4PropertyId,\n round,\n toPercent,\n} from \"../../analytics/ga4-report-utils.js\";\nimport { runReport } from \"../../services/analytics/ga4-client.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nconst dateRegex = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nexport const ecommerceTrackingHealthSchema = z.object({\n startDate: z.string().regex(dateRegex).describe(\"Start date in YYYY-MM-DD format\"),\n endDate: z.string().regex(dateRegex).describe(\"End date in YYYY-MM-DD format\"),\n propertyId: z.string().optional().describe(\"GA4 property ID. If omitted, resolves profileId mapping first and then GA4_PROPERTY_ID.\"),\n profileId: z.string().optional().describe(\"Optional business profile ID used to resolve the mapped GA4 property.\"),\n});\n\nexport async function ecommerceTrackingHealthHandler(\n params: z.infer<typeof ecommerceTrackingHealthSchema>\n) {\n try {\n const propertyId = await resolveGa4PropertyId(params.propertyId, params.profileId);\n const report = await runReport(propertyId, {\n dateRanges: [{ startDate: params.startDate, endDate: params.endDate }],\n metrics: [\n { name: \"itemViewEvents\" },\n { name: \"addToCarts\" },\n { name: \"checkouts\" },\n { name: \"transactions\" },\n { name: \"purchaseRevenue\" },\n { name: \"refundAmount\" },\n ],\n returnPropertyQuota: true,\n });\n\n const row = report.rows?.[0] ?? {};\n const itemViews = getMetricValueByName(row, report.metricHeaders, \"itemViewEvents\");\n const addToCarts = getMetricValueByName(row, report.metricHeaders, \"addToCarts\");\n const checkouts = getMetricValueByName(row, report.metricHeaders, \"checkouts\");\n const transactions = getMetricValueByName(row, report.metricHeaders, \"transactions\");\n const purchaseRevenue = getMetricValueByName(row, report.metricHeaders, \"purchaseRevenue\");\n const refundAmount = getMetricValueByName(row, report.metricHeaders, \"refundAmount\");\n\n const warnings: string[] = [];\n if (itemViews === 0) {\n warnings.push(\"No se detectaron view_item events en el rango consultado.\");\n }\n if (addToCarts === 0 && itemViews > 0) {\n warnings.push(\"Hay view_item pero no add_to_cart. Revisar tagging de add_to_cart.\");\n }\n if (checkouts === 0 && addToCarts > 0) {\n warnings.push(\"Hay add_to_cart pero no begin_checkout. Revisar continuidad del funnel.\");\n }\n if (transactions === 0 && checkouts > 0) {\n warnings.push(\"Hay begin_checkout pero no purchase/transactions. Revisar tagging de compra.\");\n }\n if (purchaseRevenue > 0 && transactions === 0) {\n warnings.push(\"Hay revenue pero no transactions. Revisar consistencia de ecommerce events.\");\n }\n\n return object(\n stripNulls({\n property_id: propertyId,\n date_range: {\n start_date: params.startDate,\n end_date: params.endDate,\n },\n currency_code: report.metadata?.currencyCode,\n funnel: {\n item_view_events: itemViews,\n add_to_carts: addToCarts,\n checkouts,\n transactions,\n purchase_revenue: round(purchaseRevenue),\n refund_amount: round(refundAmount),\n add_to_cart_rate_percent: round(toPercent(addToCarts, itemViews)),\n checkout_rate_percent: round(toPercent(checkouts, addToCarts)),\n purchase_rate_percent: round(toPercent(transactions, checkouts)),\n },\n warnings,\n quota: extractQuotaSnapshot(report),\n })\n );\n } catch (err) {\n return error(\n err instanceof Error ? err.message : \"Failed to evaluate GA4 ecommerce tracking health\"\n );\n }\n}\n"],
|
|
5
5
|
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAE3B,MAAM,YAAY;AAEX,MAAM,gCAAgC,EAAE,OAAO;AAAA,EACpD,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,iCAAiC;AAAA,EACjF,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,+BAA+B;AAAA,EAC7E,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yFAAyF;AAAA,EACpI,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,uEAAuE;AACnH,CAAC;AAED,eAAsB,+BACpB,QACA;AACA,MAAI;AACF,UAAM,aAAa,MAAM,qBAAqB,OAAO,YAAY,OAAO,SAAS;AACjF,UAAM,SAAS,MAAM,UAAU,YAAY;AAAA,MACzC,YAAY,CAAC,EAAE,WAAW,OAAO,WAAW,SAAS,OAAO,QAAQ,CAAC;AAAA,MACrE,SAAS;AAAA,QACP,EAAE,MAAM,iBAAiB;AAAA,QACzB,EAAE,MAAM,aAAa;AAAA,QACrB,EAAE,MAAM,YAAY;AAAA,QACpB,EAAE,MAAM,eAAe;AAAA,QACvB,EAAE,MAAM,kBAAkB;AAAA,QAC1B,EAAE,MAAM,eAAe;AAAA,MACzB;AAAA,MACA,qBAAqB;AAAA,IACvB,CAAC;AAED,UAAM,MAAM,OAAO,OAAO,CAAC,KAAK,CAAC;AACjC,UAAM,YAAY,qBAAqB,KAAK,OAAO,eAAe,gBAAgB;AAClF,UAAM,aAAa,qBAAqB,KAAK,OAAO,eAAe,YAAY;AAC/E,UAAM,YAAY,qBAAqB,KAAK,OAAO,eAAe,WAAW;AAC7E,UAAM,eAAe,qBAAqB,KAAK,OAAO,eAAe,cAAc;AACnF,UAAM,kBAAkB,qBAAqB,KAAK,OAAO,eAAe,iBAAiB;AACzF,UAAM,eAAe,qBAAqB,KAAK,OAAO,eAAe,cAAc;AAEnF,UAAM,WAAqB,CAAC;AAC5B,QAAI,cAAc,GAAG;AACnB,eAAS,KAAK,2DAA2D;AAAA,IAC3E;AACA,QAAI,eAAe,KAAK,YAAY,GAAG;AACrC,eAAS,KAAK,oEAAoE;AAAA,IACpF;AACA,QAAI,cAAc,KAAK,aAAa,GAAG;AACrC,eAAS,KAAK,yEAAyE;AAAA,IACzF;AACA,QAAI,iBAAiB,KAAK,YAAY,GAAG;AACvC,eAAS,KAAK,8EAA8E;AAAA,IAC9F;AACA,QAAI,kBAAkB,KAAK,iBAAiB,GAAG;AAC7C,eAAS,KAAK,6EAA6E;AAAA,IAC7F;AAEA,WAAO;AAAA,MACL,WAAW;AAAA,QACT,aAAa;AAAA,QACb,YAAY;AAAA,UACV,YAAY,OAAO;AAAA,UACnB,UAAU,OAAO;AAAA,QACnB;AAAA,QACA,eAAe,OAAO,UAAU;AAAA,QAChC,QAAQ;AAAA,UACN,kBAAkB;AAAA,UAClB,cAAc;AAAA,UACd;AAAA,UACA;AAAA,UACA,kBAAkB,MAAM,eAAe;AAAA,UACvC,eAAe,MAAM,YAAY;AAAA,UACjC,0BAA0B,MAAM,UAAU,YAAY,SAAS,CAAC;AAAA,UAChE,uBAAuB,MAAM,UAAU,WAAW,UAAU,CAAC;AAAA,UAC7D,uBAAuB,MAAM,UAAU,cAAc,SAAS,CAAC;AAAA,QACjE;AAAA,QACA;AAAA,QACA,OAAO,qBAAqB,MAAM;AAAA,MACpC,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,eAAe,QAAQ,IAAI,UAAU;AAAA,IACvC;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/analytics/engagement-overview.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport {\n extractQuotaSnapshot,\n getMetricValueByName,\n resolveGa4PropertyId,\n round,\n} from \"../../analytics/ga4-report-utils.js\";\nimport { runReport } from \"../../services/analytics/ga4-client.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nconst dateRegex = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nexport const engagementOverviewSchema = z.object({\n startDate: z.string().regex(dateRegex).describe(\"Start date in YYYY-MM-DD format\"),\n endDate: z.string().regex(dateRegex).describe(\"End date in YYYY-MM-DD format\"),\n propertyId: z.string().optional().describe(\"GA4 property ID. If omitted, resolves profileId mapping first and then GA4_PROPERTY_ID.\"),\n profileId: z.string().optional().describe(\"Optional business profile ID used to resolve the mapped GA4 property.\"),\n});\n\nexport async function engagementOverviewHandler(params: z.infer<typeof engagementOverviewSchema>) {\n try {\n const propertyId = await resolveGa4PropertyId(params.propertyId, params.profileId);\n const report = await runReport(propertyId, {\n dateRanges: [{ startDate: params.startDate, endDate: params.endDate }],\n metrics: [\n { name: \"sessions\" },\n { name: \"engagedSessions\" },\n { name: \"engagementRate\" },\n { name: \"averageSessionDuration\" },\n { name: \"screenPageViews\" },\n { name: \"screenPageViewsPerSession\" },\n { name: \"bounceRate\" },\n { name: \"userEngagementDuration\" },\n ],\n returnPropertyQuota: true,\n });\n\n const row = report.rows?.[0] ?? {};\n\n return object(\n stripNulls({\n property_id: propertyId,\n date_range: {\n start_date: params.startDate,\n end_date: params.endDate,\n },\n overview: {\n sessions: getMetricValueByName(row, report.metricHeaders, \"sessions\"),\n engaged_sessions: getMetricValueByName(row, report.metricHeaders, \"engagedSessions\"),\n engagement_rate_percent: round(\n getMetricValueByName(row, report.metricHeaders, \"engagementRate\") * 100\n ),\n bounce_rate_percent: round(getMetricValueByName(row, report.metricHeaders, \"bounceRate\") * 100),\n average_session_duration_seconds: round(\n getMetricValueByName(row, report.metricHeaders, \"averageSessionDuration\")\n ),\n views: getMetricValueByName(row, report.metricHeaders, \"screenPageViews\"),\n views_per_session: round(\n getMetricValueByName(row, report.metricHeaders, \"screenPageViewsPerSession\")\n ),\n user_engagement_duration_seconds: round(\n getMetricValueByName(row, report.metricHeaders, \"userEngagementDuration\")\n ),\n },\n quota: extractQuotaSnapshot(report),\n })\n );\n } catch (err) {\n return error(err instanceof Error ? err.message : \"Failed to fetch GA4 engagement overview\");\n }\n}\n"],
|
|
5
5
|
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAE3B,MAAM,YAAY;AAEX,MAAM,2BAA2B,EAAE,OAAO;AAAA,EAC/C,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,iCAAiC;AAAA,EACjF,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,+BAA+B;AAAA,EAC7E,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yFAAyF;AAAA,EACpI,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,uEAAuE;AACnH,CAAC;AAED,eAAsB,0BAA0B,QAAkD;AAChG,MAAI;AACF,UAAM,aAAa,MAAM,qBAAqB,OAAO,YAAY,OAAO,SAAS;AACjF,UAAM,SAAS,MAAM,UAAU,YAAY;AAAA,MACzC,YAAY,CAAC,EAAE,WAAW,OAAO,WAAW,SAAS,OAAO,QAAQ,CAAC;AAAA,MACrE,SAAS;AAAA,QACP,EAAE,MAAM,WAAW;AAAA,QACnB,EAAE,MAAM,kBAAkB;AAAA,QAC1B,EAAE,MAAM,iBAAiB;AAAA,QACzB,EAAE,MAAM,yBAAyB;AAAA,QACjC,EAAE,MAAM,kBAAkB;AAAA,QAC1B,EAAE,MAAM,4BAA4B;AAAA,QACpC,EAAE,MAAM,aAAa;AAAA,QACrB,EAAE,MAAM,yBAAyB;AAAA,MACnC;AAAA,MACA,qBAAqB;AAAA,IACvB,CAAC;AAED,UAAM,MAAM,OAAO,OAAO,CAAC,KAAK,CAAC;AAEjC,WAAO;AAAA,MACL,WAAW;AAAA,QACT,aAAa;AAAA,QACb,YAAY;AAAA,UACV,YAAY,OAAO;AAAA,UACnB,UAAU,OAAO;AAAA,QACnB;AAAA,QACA,UAAU;AAAA,UACR,UAAU,qBAAqB,KAAK,OAAO,eAAe,UAAU;AAAA,UACpE,kBAAkB,qBAAqB,KAAK,OAAO,eAAe,iBAAiB;AAAA,UACnF,yBAAyB;AAAA,YACvB,qBAAqB,KAAK,OAAO,eAAe,gBAAgB,IAAI;AAAA,UACtE;AAAA,UACA,qBAAqB,MAAM,qBAAqB,KAAK,OAAO,eAAe,YAAY,IAAI,GAAG;AAAA,UAC9F,kCAAkC;AAAA,YAChC,qBAAqB,KAAK,OAAO,eAAe,wBAAwB;AAAA,UAC1E;AAAA,UACA,OAAO,qBAAqB,KAAK,OAAO,eAAe,iBAAiB;AAAA,UACxE,mBAAmB;AAAA,YACjB,qBAAqB,KAAK,OAAO,eAAe,2BAA2B;AAAA,UAC7E;AAAA,UACA,kCAAkC;AAAA,YAChC,qBAAqB,KAAK,OAAO,eAAe,wBAAwB;AAAA,UAC1E;AAAA,QACF;AAAA,QACA,OAAO,qBAAqB,MAAM;AAAA,MACpC,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,MAAM,eAAe,QAAQ,IAAI,UAAU,yCAAyC;AAAA,EAC7F;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/analytics/index.ts"],
|
|
4
|
-
"sourcesContent": ["export * from \"./list-accessible-properties.js\";\
|
|
4
|
+
"sourcesContent": ["export * from \"./list-accessible-properties.js\";\nexport * from \"./property-info.js\";\nexport * from \"./channel-mix.js\";\nexport * from \"./source-medium-breakdown.js\";\nexport * from \"./revenue-overview.js\";\nexport * from \"./revenue-trend.js\";\nexport * from \"./revenue-by-channel.js\";\nexport * from \"./top-landing-pages.js\";\nexport * from \"./engagement-overview.js\";\nexport * from \"./attribution-gaps.js\";\nexport * from \"./ecommerce-tracking-health.js\";\n"],
|
|
5
5
|
"mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/analytics/list-accessible-properties.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { listAccountSummaries } from \"../../services/analytics/ga4-client.js\";\nimport { getDefaultGa4PropertyId } from \"../../config/google.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nexport const listAccessiblePropertiesSchema = z.object({});\n\nexport async function listAccessiblePropertiesHandler(\n _params: z.infer<typeof listAccessiblePropertiesSchema>\n) {\n try {\n const { accountSummaries, nextPageToken } = await listAccountSummaries();\n const defaultPropertyId = getDefaultGa4PropertyId();\n\n const accounts = accountSummaries.map((account) => ({\n account_id: account.account.replace(\"accounts/\", \"\"),\n account_name: account.displayName,\n properties: (account.propertySummaries ?? []).map((property) => {\n const propertyId = property.property.replace(\"properties/\", \"\");\n\n return {\n property_id: propertyId,\n property_name: property.displayName,\n property_type: property.propertyType,\n is_default_property: propertyId === defaultPropertyId,\n };\n }),\n }));\n\n const totalProperties = accounts.reduce((total, account) => total + account.properties.length, 0);\n\n return object(\n stripNulls({\n metadata: {\n is_partial: Boolean(nextPageToken),\n next_page_token: nextPageToken,\n continuation_instructions: nextPageToken\n ? \"This response includes only the first page of accessible GA4 account summaries. Do not assume the account or property list is complete. If you need the full universe, request the next page using next_page_token.\"\n : undefined,\n },\n total_accounts: accounts.length,\n total_properties: totalProperties,\n default_property_id: defaultPropertyId,\n accounts,\n })\n );\n } catch (err) {\n return error(err instanceof Error ? err.message : \"Failed to list accessible GA4 properties\");\n }\n}\n"],
|
|
5
5
|
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,4BAA4B;AACrC,SAAS,+BAA+B;AACxC,SAAS,kBAAkB;AAEpB,MAAM,iCAAiC,EAAE,OAAO,CAAC,CAAC;AAEzD,eAAsB,gCACpB,SACA;AACA,MAAI;AACF,UAAM,EAAE,kBAAkB,cAAc,IAAI,MAAM,qBAAqB;AACvE,UAAM,oBAAoB,wBAAwB;AAElD,UAAM,WAAW,iBAAiB,IAAI,CAAC,aAAa;AAAA,MAClD,YAAY,QAAQ,QAAQ,QAAQ,aAAa,EAAE;AAAA,MACnD,cAAc,QAAQ;AAAA,MACtB,aAAa,QAAQ,qBAAqB,CAAC,GAAG,IAAI,CAAC,aAAa;AAC9D,cAAM,aAAa,SAAS,SAAS,QAAQ,eAAe,EAAE;AAE9D,eAAO;AAAA,UACL,aAAa;AAAA,UACb,eAAe,SAAS;AAAA,UACxB,eAAe,SAAS;AAAA,UACxB,qBAAqB,eAAe;AAAA,QACtC;AAAA,MACF,CAAC;AAAA,IACH,EAAE;AAEF,UAAM,kBAAkB,SAAS,OAAO,CAAC,OAAO,YAAY,QAAQ,QAAQ,WAAW,QAAQ,CAAC;AAEhG,WAAO;AAAA,MACL,WAAW;AAAA,QACT,UAAU;AAAA,UACR,YAAY,QAAQ,aAAa;AAAA,UACjC,iBAAiB;AAAA,UACjB,2BAA2B,gBACvB,wNACA;AAAA,QACN;AAAA,QACA,gBAAgB,SAAS;AAAA,QACzB,kBAAkB;AAAA,QAClB,qBAAqB;AAAA,QACrB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,MAAM,eAAe,QAAQ,IAAI,UAAU,0CAA0C;AAAA,EAC9F;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/analytics/property-info.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { findPropertySummary, resolveGa4PropertyId } from \"../../analytics/ga4-report-utils.js\";\nimport { getMetadata, listAccountSummaries } from \"../../services/analytics/ga4-client.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nexport const propertyInfoSchema = z.object({\n propertyId: z.string().optional().describe(\"GA4 property ID. If omitted, resolves profileId mapping first and then GA4_PROPERTY_ID.\"),\n profileId: z.string().optional().describe(\"Optional business profile ID used to resolve the mapped GA4 property.\"),\n});\n\nexport async function propertyInfoHandler(params: z.infer<typeof propertyInfoSchema>) {\n try {\n const propertyId = await resolveGa4PropertyId(params.propertyId, params.profileId);\n\n const [{ accountSummaries }, metadata] = await Promise.all([\n listAccountSummaries(),\n getMetadata(propertyId),\n ]);\n\n const propertySummary = findPropertySummary(accountSummaries, propertyId);\n const dimensions = metadata.dimensions ?? [];\n const metrics = metadata.metrics ?? [];\n\n return object(\n stripNulls({\n property: {\n property_id: propertyId,\n property_name: propertySummary?.propertyName,\n property_type: propertySummary?.propertyType,\n account_id: propertySummary?.accountId,\n account_name: propertySummary?.accountName,\n },\n capabilities: {\n supports_ecommerce:\n metrics.some((metric) => metric.apiName === \"purchaseRevenue\") &&\n metrics.some((metric) => metric.apiName === \"transactions\"),\n supports_google_ads_dimensions: dimensions.some((dimension) =>\n dimension.apiName.startsWith(\"sessionGoogleAds\")\n ),\n supports_search_console_metrics: metrics.some((metric) =>\n metric.apiName.startsWith(\"organicGoogleSearch\")\n ),\n custom_channel_groups: dimensions\n .filter((dimension) => dimension.apiName.includes(\"CustomChannelGroup\"))\n .map((dimension) => dimension.apiName),\n },\n metadata_summary: {\n total_dimensions: dimensions.length,\n total_metrics: metrics.length,\n sample_dimensions: dimensions.slice(0, 12).map((dimension) => dimension.apiName),\n sample_metrics: metrics.slice(0, 12).map((metric) => metric.apiName),\n },\n })\n );\n } catch (err) {\n return error(err instanceof Error ? err.message : \"Failed to fetch GA4 property info\");\n }\n}\n"],
|
|
5
5
|
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,qBAAqB,4BAA4B;AAC1D,SAAS,aAAa,4BAA4B;AAClD,SAAS,kBAAkB;AAEpB,MAAM,qBAAqB,EAAE,OAAO;AAAA,EACzC,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yFAAyF;AAAA,EACpI,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,uEAAuE;AACnH,CAAC;AAED,eAAsB,oBAAoB,QAA4C;AACpF,MAAI;AACF,UAAM,aAAa,MAAM,qBAAqB,OAAO,YAAY,OAAO,SAAS;AAEjF,UAAM,CAAC,EAAE,iBAAiB,GAAG,QAAQ,IAAI,MAAM,QAAQ,IAAI;AAAA,MACzD,qBAAqB;AAAA,MACrB,YAAY,UAAU;AAAA,IACxB,CAAC;AAED,UAAM,kBAAkB,oBAAoB,kBAAkB,UAAU;AACxE,UAAM,aAAa,SAAS,cAAc,CAAC;AAC3C,UAAM,UAAU,SAAS,WAAW,CAAC;AAErC,WAAO;AAAA,MACL,WAAW;AAAA,QACT,UAAU;AAAA,UACR,aAAa;AAAA,UACb,eAAe,iBAAiB;AAAA,UAChC,eAAe,iBAAiB;AAAA,UAChC,YAAY,iBAAiB;AAAA,UAC7B,cAAc,iBAAiB;AAAA,QACjC;AAAA,QACA,cAAc;AAAA,UACZ,oBACE,QAAQ,KAAK,CAAC,WAAW,OAAO,YAAY,iBAAiB,KAC7D,QAAQ,KAAK,CAAC,WAAW,OAAO,YAAY,cAAc;AAAA,UAC5D,gCAAgC,WAAW;AAAA,YAAK,CAAC,cAC/C,UAAU,QAAQ,WAAW,kBAAkB;AAAA,UACjD;AAAA,UACA,iCAAiC,QAAQ;AAAA,YAAK,CAAC,WAC7C,OAAO,QAAQ,WAAW,qBAAqB;AAAA,UACjD;AAAA,UACA,uBAAuB,WACpB,OAAO,CAAC,cAAc,UAAU,QAAQ,SAAS,oBAAoB,CAAC,EACtE,IAAI,CAAC,cAAc,UAAU,OAAO;AAAA,QACzC;AAAA,QACA,kBAAkB;AAAA,UAChB,kBAAkB,WAAW;AAAA,UAC7B,eAAe,QAAQ;AAAA,UACvB,mBAAmB,WAAW,MAAM,GAAG,EAAE,EAAE,IAAI,CAAC,cAAc,UAAU,OAAO;AAAA,UAC/E,gBAAgB,QAAQ,MAAM,GAAG,EAAE,EAAE,IAAI,CAAC,WAAW,OAAO,OAAO;AAAA,QACrE;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,MAAM,eAAe,QAAQ,IAAI,UAAU,mCAAmC;AAAA,EACvF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/analytics/revenue-by-channel.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport {\n extractQuotaSnapshot,\n getDimensionValue,\n getMetricValueByName,\n resolveGa4PropertyId,\n round,\n sumMetricValues,\n toPercent,\n} from \"../../analytics/ga4-report-utils.js\";\nimport { runReport } from \"../../services/analytics/ga4-client.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nconst dateRegex = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nexport const revenueByChannelSchema = z.object({\n startDate: z.string().regex(dateRegex).describe(\"Start date in YYYY-MM-DD format\"),\n endDate: z.string().regex(dateRegex).describe(\"End date in YYYY-MM-DD format\"),\n propertyId: z.string().optional().describe(\"GA4 property ID. If omitted, resolves profileId mapping first and then GA4_PROPERTY_ID.\"),\n profileId: z.string().optional().describe(\"Optional business profile ID used to resolve the mapped GA4 property.\"),\n});\n\nexport async function revenueByChannelHandler(params: z.infer<typeof revenueByChannelSchema>) {\n try {\n const propertyId = await resolveGa4PropertyId(params.propertyId, params.profileId);\n const report = await runReport(propertyId, {\n dateRanges: [{ startDate: params.startDate, endDate: params.endDate }],\n dimensions: [{ name: \"sessionDefaultChannelGroup\" }],\n metrics: [{ name: \"transactions\" }, { name: \"purchaseRevenue\" }, { name: \"sessions\" }],\n orderBys: [{ metric: { metricName: \"purchaseRevenue\" }, desc: true }],\n returnPropertyQuota: true,\n });\n\n const totalRevenue = sumMetricValues(report.rows, report.metricHeaders, \"purchaseRevenue\");\n const totalTransactions = sumMetricValues(report.rows, report.metricHeaders, \"transactions\");\n\n const channels = (report.rows ?? []).map((row) => {\n const revenue = getMetricValueByName(row, report.metricHeaders, \"purchaseRevenue\");\n const transactions = getMetricValueByName(row, report.metricHeaders, \"transactions\");\n const sessions = getMetricValueByName(row, report.metricHeaders, \"sessions\");\n\n return {\n channel: getDimensionValue(row),\n sessions,\n transactions,\n purchase_revenue: round(revenue),\n revenue_share_percent: round(toPercent(revenue, totalRevenue)),\n transaction_share_percent: round(toPercent(transactions, totalTransactions)),\n };\n });\n\n return object(\n stripNulls({\n property_id: propertyId,\n date_range: {\n start_date: params.startDate,\n end_date: params.endDate,\n },\n currency_code: report.metadata?.currencyCode,\n overview: {\n total_purchase_revenue: round(totalRevenue),\n total_transactions: totalTransactions,\n top_revenue_channel: channels[0]?.channel,\n },\n channels,\n quota: extractQuotaSnapshot(report),\n })\n );\n } catch (err) {\n return error(err instanceof Error ? err.message : \"Failed to fetch GA4 revenue by channel\");\n }\n}\n"],
|
|
5
5
|
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAE3B,MAAM,YAAY;AAEX,MAAM,yBAAyB,EAAE,OAAO;AAAA,EAC7C,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,iCAAiC;AAAA,EACjF,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,+BAA+B;AAAA,EAC7E,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yFAAyF;AAAA,EACpI,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,uEAAuE;AACnH,CAAC;AAED,eAAsB,wBAAwB,QAAgD;AAC5F,MAAI;AACF,UAAM,aAAa,MAAM,qBAAqB,OAAO,YAAY,OAAO,SAAS;AACjF,UAAM,SAAS,MAAM,UAAU,YAAY;AAAA,MACzC,YAAY,CAAC,EAAE,WAAW,OAAO,WAAW,SAAS,OAAO,QAAQ,CAAC;AAAA,MACrE,YAAY,CAAC,EAAE,MAAM,6BAA6B,CAAC;AAAA,MACnD,SAAS,CAAC,EAAE,MAAM,eAAe,GAAG,EAAE,MAAM,kBAAkB,GAAG,EAAE,MAAM,WAAW,CAAC;AAAA,MACrF,UAAU,CAAC,EAAE,QAAQ,EAAE,YAAY,kBAAkB,GAAG,MAAM,KAAK,CAAC;AAAA,MACpE,qBAAqB;AAAA,IACvB,CAAC;AAED,UAAM,eAAe,gBAAgB,OAAO,MAAM,OAAO,eAAe,iBAAiB;AACzF,UAAM,oBAAoB,gBAAgB,OAAO,MAAM,OAAO,eAAe,cAAc;AAE3F,UAAM,YAAY,OAAO,QAAQ,CAAC,GAAG,IAAI,CAAC,QAAQ;AAChD,YAAM,UAAU,qBAAqB,KAAK,OAAO,eAAe,iBAAiB;AACjF,YAAM,eAAe,qBAAqB,KAAK,OAAO,eAAe,cAAc;AACnF,YAAM,WAAW,qBAAqB,KAAK,OAAO,eAAe,UAAU;AAE3E,aAAO;AAAA,QACL,SAAS,kBAAkB,GAAG;AAAA,QAC9B;AAAA,QACA;AAAA,QACA,kBAAkB,MAAM,OAAO;AAAA,QAC/B,uBAAuB,MAAM,UAAU,SAAS,YAAY,CAAC;AAAA,QAC7D,2BAA2B,MAAM,UAAU,cAAc,iBAAiB,CAAC;AAAA,MAC7E;AAAA,IACF,CAAC;AAED,WAAO;AAAA,MACL,WAAW;AAAA,QACT,aAAa;AAAA,QACb,YAAY;AAAA,UACV,YAAY,OAAO;AAAA,UACnB,UAAU,OAAO;AAAA,QACnB;AAAA,QACA,eAAe,OAAO,UAAU;AAAA,QAChC,UAAU;AAAA,UACR,wBAAwB,MAAM,YAAY;AAAA,UAC1C,oBAAoB;AAAA,UACpB,qBAAqB,SAAS,CAAC,GAAG;AAAA,QACpC;AAAA,QACA;AAAA,QACA,OAAO,qBAAqB,MAAM;AAAA,MACpC,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,MAAM,eAAe,QAAQ,IAAI,UAAU,wCAAwC;AAAA,EAC5F;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/analytics/revenue-overview.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport {\n extractQuotaSnapshot,\n getMetricValueByName,\n resolveGa4PropertyId,\n round,\n toPercent,\n} from \"../../analytics/ga4-report-utils.js\";\nimport { runReport } from \"../../services/analytics/ga4-client.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nconst dateRegex = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nexport const revenueOverviewSchema = z.object({\n startDate: z.string().regex(dateRegex).describe(\"Start date in YYYY-MM-DD format\"),\n endDate: z.string().regex(dateRegex).describe(\"End date in YYYY-MM-DD format\"),\n propertyId: z.string().optional().describe(\"GA4 property ID. If omitted, resolves profileId mapping first and then GA4_PROPERTY_ID.\"),\n profileId: z.string().optional().describe(\"Optional business profile ID used to resolve the mapped GA4 property.\"),\n});\n\nexport async function revenueOverviewHandler(params: z.infer<typeof revenueOverviewSchema>) {\n try {\n const propertyId = await resolveGa4PropertyId(params.propertyId, params.profileId);\n const report = await runReport(propertyId, {\n dateRanges: [{ startDate: params.startDate, endDate: params.endDate }],\n metrics: [\n { name: \"sessions\" },\n { name: \"totalUsers\" },\n { name: \"transactions\" },\n { name: \"purchaseRevenue\" },\n { name: \"averagePurchaseRevenue\" },\n { name: \"totalPurchasers\" },\n { name: \"purchaserRate\" },\n ],\n returnPropertyQuota: true,\n });\n\n const row = report.rows?.[0] ?? {};\n const sessions = getMetricValueByName(row, report.metricHeaders, \"sessions\");\n const totalUsers = getMetricValueByName(row, report.metricHeaders, \"totalUsers\");\n const transactions = getMetricValueByName(row, report.metricHeaders, \"transactions\");\n const purchaseRevenue = getMetricValueByName(row, report.metricHeaders, \"purchaseRevenue\");\n const averagePurchaseRevenue = getMetricValueByName(\n row,\n report.metricHeaders,\n \"averagePurchaseRevenue\"\n );\n const totalPurchasers = getMetricValueByName(row, report.metricHeaders, \"totalPurchasers\");\n const purchaserRate = getMetricValueByName(row, report.metricHeaders, \"purchaserRate\");\n\n return object(\n stripNulls({\n property_id: propertyId,\n date_range: {\n start_date: params.startDate,\n end_date: params.endDate,\n },\n currency_code: report.metadata?.currencyCode,\n overview: {\n sessions,\n total_users: totalUsers,\n transactions,\n total_purchasers: totalPurchasers,\n purchase_revenue: round(purchaseRevenue),\n average_purchase_revenue: round(averagePurchaseRevenue),\n purchaser_rate_percent: round(purchaserRate * 100),\n transactions_per_session_percent: round(toPercent(transactions, sessions)),\n transactions_per_user_percent: round(toPercent(transactions, totalUsers)),\n revenue_per_session: round(sessions > 0 ? purchaseRevenue / sessions : 0),\n },\n quota: extractQuotaSnapshot(report),\n })\n );\n } catch (err) {\n return error(err instanceof Error ? err.message : \"Failed to fetch GA4 revenue overview\");\n }\n}\n"],
|
|
5
5
|
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAE3B,MAAM,YAAY;AAEX,MAAM,wBAAwB,EAAE,OAAO;AAAA,EAC5C,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,iCAAiC;AAAA,EACjF,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,+BAA+B;AAAA,EAC7E,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yFAAyF;AAAA,EACpI,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,uEAAuE;AACnH,CAAC;AAED,eAAsB,uBAAuB,QAA+C;AAC1F,MAAI;AACF,UAAM,aAAa,MAAM,qBAAqB,OAAO,YAAY,OAAO,SAAS;AACjF,UAAM,SAAS,MAAM,UAAU,YAAY;AAAA,MACzC,YAAY,CAAC,EAAE,WAAW,OAAO,WAAW,SAAS,OAAO,QAAQ,CAAC;AAAA,MACrE,SAAS;AAAA,QACP,EAAE,MAAM,WAAW;AAAA,QACnB,EAAE,MAAM,aAAa;AAAA,QACrB,EAAE,MAAM,eAAe;AAAA,QACvB,EAAE,MAAM,kBAAkB;AAAA,QAC1B,EAAE,MAAM,yBAAyB;AAAA,QACjC,EAAE,MAAM,kBAAkB;AAAA,QAC1B,EAAE,MAAM,gBAAgB;AAAA,MAC1B;AAAA,MACA,qBAAqB;AAAA,IACvB,CAAC;AAED,UAAM,MAAM,OAAO,OAAO,CAAC,KAAK,CAAC;AACjC,UAAM,WAAW,qBAAqB,KAAK,OAAO,eAAe,UAAU;AAC3E,UAAM,aAAa,qBAAqB,KAAK,OAAO,eAAe,YAAY;AAC/E,UAAM,eAAe,qBAAqB,KAAK,OAAO,eAAe,cAAc;AACnF,UAAM,kBAAkB,qBAAqB,KAAK,OAAO,eAAe,iBAAiB;AACzF,UAAM,yBAAyB;AAAA,MAC7B;AAAA,MACA,OAAO;AAAA,MACP;AAAA,IACF;AACA,UAAM,kBAAkB,qBAAqB,KAAK,OAAO,eAAe,iBAAiB;AACzF,UAAM,gBAAgB,qBAAqB,KAAK,OAAO,eAAe,eAAe;AAErF,WAAO;AAAA,MACL,WAAW;AAAA,QACT,aAAa;AAAA,QACb,YAAY;AAAA,UACV,YAAY,OAAO;AAAA,UACnB,UAAU,OAAO;AAAA,QACnB;AAAA,QACA,eAAe,OAAO,UAAU;AAAA,QAChC,UAAU;AAAA,UACR;AAAA,UACA,aAAa;AAAA,UACb;AAAA,UACA,kBAAkB;AAAA,UAClB,kBAAkB,MAAM,eAAe;AAAA,UACvC,0BAA0B,MAAM,sBAAsB;AAAA,UACtD,wBAAwB,MAAM,gBAAgB,GAAG;AAAA,UACjD,kCAAkC,MAAM,UAAU,cAAc,QAAQ,CAAC;AAAA,UACzE,+BAA+B,MAAM,UAAU,cAAc,UAAU,CAAC;AAAA,UACxE,qBAAqB,MAAM,WAAW,IAAI,kBAAkB,WAAW,CAAC;AAAA,QAC1E;AAAA,QACA,OAAO,qBAAqB,MAAM;AAAA,MACpC,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,MAAM,eAAe,QAAQ,IAAI,UAAU,sCAAsC;AAAA,EAC1F;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/analytics/revenue-trend.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport {\n extractQuotaSnapshot,\n formatGa4Date,\n getDimensionValue,\n getMetricValueByName,\n resolveGa4PropertyId,\n round,\n} from \"../../analytics/ga4-report-utils.js\";\nimport { runReport } from \"../../services/analytics/ga4-client.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nconst dateRegex = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nexport const revenueTrendSchema = z.object({\n startDate: z.string().regex(dateRegex).describe(\"Start date in YYYY-MM-DD format\"),\n endDate: z.string().regex(dateRegex).describe(\"End date in YYYY-MM-DD format\"),\n propertyId: z.string().optional().describe(\"GA4 property ID. If omitted, resolves profileId mapping first and then GA4_PROPERTY_ID.\"),\n profileId: z.string().optional().describe(\"Optional business profile ID used to resolve the mapped GA4 property.\"),\n});\n\nexport async function revenueTrendHandler(params: z.infer<typeof revenueTrendSchema>) {\n try {\n const propertyId = await resolveGa4PropertyId(params.propertyId, params.profileId);\n const report = await runReport(propertyId, {\n dateRanges: [{ startDate: params.startDate, endDate: params.endDate }],\n dimensions: [{ name: \"date\" }],\n metrics: [{ name: \"transactions\" }, { name: \"purchaseRevenue\" }],\n orderBys: [{ dimension: { dimensionName: \"date\" } }],\n returnPropertyQuota: true,\n });\n\n const daily = (report.rows ?? []).map((row) => ({\n date: formatGa4Date(getDimensionValue(row)),\n transactions: getMetricValueByName(row, report.metricHeaders, \"transactions\"),\n purchase_revenue: round(getMetricValueByName(row, report.metricHeaders, \"purchaseRevenue\")),\n }));\n\n const totalRevenue = daily.reduce((total, day) => total + day.purchase_revenue, 0);\n const totalTransactions = daily.reduce((total, day) => total + day.transactions, 0);\n const topRevenueDay = daily.reduce<(typeof daily)[number] | undefined>((currentTop, day) => {\n if (!currentTop || day.purchase_revenue > currentTop.purchase_revenue) {\n return day;\n }\n\n return currentTop;\n }, undefined);\n\n return object(\n stripNulls({\n property_id: propertyId,\n date_range: {\n start_date: params.startDate,\n end_date: params.endDate,\n },\n currency_code: report.metadata?.currencyCode,\n overview: {\n days: daily.length,\n total_transactions: totalTransactions,\n total_purchase_revenue: round(totalRevenue),\n average_daily_revenue: round(daily.length > 0 ? totalRevenue / daily.length : 0),\n top_revenue_day: topRevenueDay,\n },\n daily,\n quota: extractQuotaSnapshot(report),\n })\n );\n } catch (err) {\n return error(err instanceof Error ? err.message : \"Failed to fetch GA4 revenue trend\");\n }\n}\n"],
|
|
5
5
|
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAE3B,MAAM,YAAY;AAEX,MAAM,qBAAqB,EAAE,OAAO;AAAA,EACzC,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,iCAAiC;AAAA,EACjF,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,+BAA+B;AAAA,EAC7E,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yFAAyF;AAAA,EACpI,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,uEAAuE;AACnH,CAAC;AAED,eAAsB,oBAAoB,QAA4C;AACpF,MAAI;AACF,UAAM,aAAa,MAAM,qBAAqB,OAAO,YAAY,OAAO,SAAS;AACjF,UAAM,SAAS,MAAM,UAAU,YAAY;AAAA,MACzC,YAAY,CAAC,EAAE,WAAW,OAAO,WAAW,SAAS,OAAO,QAAQ,CAAC;AAAA,MACrE,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC;AAAA,MAC7B,SAAS,CAAC,EAAE,MAAM,eAAe,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAAA,MAC/D,UAAU,CAAC,EAAE,WAAW,EAAE,eAAe,OAAO,EAAE,CAAC;AAAA,MACnD,qBAAqB;AAAA,IACvB,CAAC;AAED,UAAM,SAAS,OAAO,QAAQ,CAAC,GAAG,IAAI,CAAC,SAAS;AAAA,MAC9C,MAAM,cAAc,kBAAkB,GAAG,CAAC;AAAA,MAC1C,cAAc,qBAAqB,KAAK,OAAO,eAAe,cAAc;AAAA,MAC5E,kBAAkB,MAAM,qBAAqB,KAAK,OAAO,eAAe,iBAAiB,CAAC;AAAA,IAC5F,EAAE;AAEF,UAAM,eAAe,MAAM,OAAO,CAAC,OAAO,QAAQ,QAAQ,IAAI,kBAAkB,CAAC;AACjF,UAAM,oBAAoB,MAAM,OAAO,CAAC,OAAO,QAAQ,QAAQ,IAAI,cAAc,CAAC;AAClF,UAAM,gBAAgB,MAAM,OAA2C,CAAC,YAAY,QAAQ;AAC1F,UAAI,CAAC,cAAc,IAAI,mBAAmB,WAAW,kBAAkB;AACrE,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT,GAAG,MAAS;AAEZ,WAAO;AAAA,MACL,WAAW;AAAA,QACT,aAAa;AAAA,QACb,YAAY;AAAA,UACV,YAAY,OAAO;AAAA,UACnB,UAAU,OAAO;AAAA,QACnB;AAAA,QACA,eAAe,OAAO,UAAU;AAAA,QAChC,UAAU;AAAA,UACR,MAAM,MAAM;AAAA,UACZ,oBAAoB;AAAA,UACpB,wBAAwB,MAAM,YAAY;AAAA,UAC1C,uBAAuB,MAAM,MAAM,SAAS,IAAI,eAAe,MAAM,SAAS,CAAC;AAAA,UAC/E,iBAAiB;AAAA,QACnB;AAAA,QACA;AAAA,QACA,OAAO,qBAAqB,MAAM;AAAA,MACpC,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,MAAM,eAAe,QAAQ,IAAI,UAAU,mCAAmC;AAAA,EACvF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/analytics/source-medium-breakdown.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport {\n extractQuotaSnapshot,\n getDimensionValue,\n getMetricValueByName,\n resolveGa4PropertyId,\n round,\n toPercent,\n} from \"../../analytics/ga4-report-utils.js\";\nimport { runReport } from \"../../services/analytics/ga4-client.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nconst dateRegex = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nexport const sourceMediumBreakdownSchema = z.object({\n startDate: z.string().regex(dateRegex).describe(\"Start date in YYYY-MM-DD format\"),\n endDate: z.string().regex(dateRegex).describe(\"End date in YYYY-MM-DD format\"),\n propertyId: z.string().optional().describe(\"GA4 property ID. If omitted, resolves profileId mapping first and then GA4_PROPERTY_ID.\"),\n profileId: z.string().optional().describe(\"Optional business profile ID used to resolve the mapped GA4 property.\"),\n limit: z.number().int().min(1).max(100).optional().describe(\"Maximum rows to return\"),\n});\n\nexport async function sourceMediumBreakdownHandler(\n params: z.infer<typeof sourceMediumBreakdownSchema>\n) {\n try {\n const propertyId = await resolveGa4PropertyId(params.propertyId, params.profileId);\n const limit = params.limit ?? 20;\n\n const [breakdownReport, totalReport] = await Promise.all([\n runReport(propertyId, {\n dateRanges: [{ startDate: params.startDate, endDate: params.endDate }],\n dimensions: [{ name: \"sessionSourceMedium\" }],\n metrics: [{ name: \"sessions\" }, { name: \"totalUsers\" }],\n orderBys: [{ metric: { metricName: \"sessions\" }, desc: true }],\n limit,\n returnPropertyQuota: true,\n }),\n runReport(propertyId, {\n dateRanges: [{ startDate: params.startDate, endDate: params.endDate }],\n metrics: [{ name: \"sessions\" }, { name: \"totalUsers\" }],\n }),\n ]);\n\n const totalSessions = getMetricValueByName(\n totalReport.rows?.[0] ?? {},\n totalReport.metricHeaders,\n \"sessions\"\n );\n const totalUsers = getMetricValueByName(\n totalReport.rows?.[0] ?? {},\n totalReport.metricHeaders,\n \"totalUsers\"\n );\n\n const rows = (breakdownReport.rows ?? []).map((row) => {\n const sessions = getMetricValueByName(row, breakdownReport.metricHeaders, \"sessions\");\n const users = getMetricValueByName(row, breakdownReport.metricHeaders, \"totalUsers\");\n\n return {\n source_medium: getDimensionValue(row),\n sessions,\n users,\n session_share_percent: round(toPercent(sessions, totalSessions)),\n user_share_percent: round(toPercent(users, totalUsers)),\n };\n });\n\n return object(\n stripNulls({\n property_id: propertyId,\n date_range: {\n start_date: params.startDate,\n end_date: params.endDate,\n },\n overview: {\n total_sessions: totalSessions,\n total_users: totalUsers,\n returned_rows: rows.length,\n available_rows: breakdownReport.rowCount,\n },\n source_mediums: rows,\n quota: extractQuotaSnapshot(breakdownReport),\n })\n );\n } catch (err) {\n return error(\n err instanceof Error ? err.message : \"Failed to fetch GA4 source / medium breakdown\"\n );\n }\n}\n"],
|
|
5
5
|
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAE3B,MAAM,YAAY;AAEX,MAAM,8BAA8B,EAAE,OAAO;AAAA,EAClD,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,iCAAiC;AAAA,EACjF,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,+BAA+B;AAAA,EAC7E,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yFAAyF;AAAA,EACpI,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,uEAAuE;AAAA,EACjH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,wBAAwB;AACtF,CAAC;AAED,eAAsB,6BACpB,QACA;AACA,MAAI;AACF,UAAM,aAAa,MAAM,qBAAqB,OAAO,YAAY,OAAO,SAAS;AACjF,UAAM,QAAQ,OAAO,SAAS;AAE9B,UAAM,CAAC,iBAAiB,WAAW,IAAI,MAAM,QAAQ,IAAI;AAAA,MACvD,UAAU,YAAY;AAAA,QACpB,YAAY,CAAC,EAAE,WAAW,OAAO,WAAW,SAAS,OAAO,QAAQ,CAAC;AAAA,QACrE,YAAY,CAAC,EAAE,MAAM,sBAAsB,CAAC;AAAA,QAC5C,SAAS,CAAC,EAAE,MAAM,WAAW,GAAG,EAAE,MAAM,aAAa,CAAC;AAAA,QACtD,UAAU,CAAC,EAAE,QAAQ,EAAE,YAAY,WAAW,GAAG,MAAM,KAAK,CAAC;AAAA,QAC7D;AAAA,QACA,qBAAqB;AAAA,MACvB,CAAC;AAAA,MACD,UAAU,YAAY;AAAA,QACpB,YAAY,CAAC,EAAE,WAAW,OAAO,WAAW,SAAS,OAAO,QAAQ,CAAC;AAAA,QACrE,SAAS,CAAC,EAAE,MAAM,WAAW,GAAG,EAAE,MAAM,aAAa,CAAC;AAAA,MACxD,CAAC;AAAA,IACH,CAAC;AAED,UAAM,gBAAgB;AAAA,MACpB,YAAY,OAAO,CAAC,KAAK,CAAC;AAAA,MAC1B,YAAY;AAAA,MACZ;AAAA,IACF;AACA,UAAM,aAAa;AAAA,MACjB,YAAY,OAAO,CAAC,KAAK,CAAC;AAAA,MAC1B,YAAY;AAAA,MACZ;AAAA,IACF;AAEA,UAAM,QAAQ,gBAAgB,QAAQ,CAAC,GAAG,IAAI,CAAC,QAAQ;AACrD,YAAM,WAAW,qBAAqB,KAAK,gBAAgB,eAAe,UAAU;AACpF,YAAM,QAAQ,qBAAqB,KAAK,gBAAgB,eAAe,YAAY;AAEnF,aAAO;AAAA,QACL,eAAe,kBAAkB,GAAG;AAAA,QACpC;AAAA,QACA;AAAA,QACA,uBAAuB,MAAM,UAAU,UAAU,aAAa,CAAC;AAAA,QAC/D,oBAAoB,MAAM,UAAU,OAAO,UAAU,CAAC;AAAA,MACxD;AAAA,IACF,CAAC;AAED,WAAO;AAAA,MACL,WAAW;AAAA,QACT,aAAa;AAAA,QACb,YAAY;AAAA,UACV,YAAY,OAAO;AAAA,UACnB,UAAU,OAAO;AAAA,QACnB;AAAA,QACA,UAAU;AAAA,UACR,gBAAgB;AAAA,UAChB,aAAa;AAAA,UACb,eAAe,KAAK;AAAA,UACpB,gBAAgB,gBAAgB;AAAA,QAClC;AAAA,QACA,gBAAgB;AAAA,QAChB,OAAO,qBAAqB,eAAe;AAAA,MAC7C,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,eAAe,QAAQ,IAAI,UAAU;AAAA,IACvC;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/analytics/top-landing-pages.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport {\n extractQuotaSnapshot,\n getDimensionValue,\n getMetricValueByName,\n resolveGa4PropertyId,\n round,\n toPercent,\n} from \"../../analytics/ga4-report-utils.js\";\nimport { runReport } from \"../../services/analytics/ga4-client.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nconst dateRegex = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nexport const topLandingPagesSchema = z.object({\n startDate: z.string().regex(dateRegex).describe(\"Start date in YYYY-MM-DD format\"),\n endDate: z.string().regex(dateRegex).describe(\"End date in YYYY-MM-DD format\"),\n propertyId: z.string().optional().describe(\"GA4 property ID. If omitted, resolves profileId mapping first and then GA4_PROPERTY_ID.\"),\n profileId: z.string().optional().describe(\"Optional business profile ID used to resolve the mapped GA4 property.\"),\n limit: z.number().int().min(1).max(100).optional().describe(\"Maximum rows to return\"),\n});\n\nexport async function topLandingPagesHandler(params: z.infer<typeof topLandingPagesSchema>) {\n try {\n const propertyId = await resolveGa4PropertyId(params.propertyId, params.profileId);\n const limit = params.limit ?? 20;\n\n const [landingReport, totalReport] = await Promise.all([\n runReport(propertyId, {\n dateRanges: [{ startDate: params.startDate, endDate: params.endDate }],\n dimensions: [{ name: \"landingPage\" }],\n metrics: [{ name: \"sessions\" }, { name: \"totalUsers\" }],\n orderBys: [{ metric: { metricName: \"sessions\" }, desc: true }],\n limit,\n returnPropertyQuota: true,\n }),\n runReport(propertyId, {\n dateRanges: [{ startDate: params.startDate, endDate: params.endDate }],\n metrics: [{ name: \"sessions\" }, { name: \"totalUsers\" }],\n }),\n ]);\n\n const totalSessions = getMetricValueByName(\n totalReport.rows?.[0] ?? {},\n totalReport.metricHeaders,\n \"sessions\"\n );\n\n const landingPages = (landingReport.rows ?? []).map((row) => {\n const sessions = getMetricValueByName(row, landingReport.metricHeaders, \"sessions\");\n const users = getMetricValueByName(row, landingReport.metricHeaders, \"totalUsers\");\n\n return {\n landing_page: getDimensionValue(row),\n sessions,\n users,\n session_share_percent: round(toPercent(sessions, totalSessions)),\n is_not_set: getDimensionValue(row) === \"(not set)\",\n };\n });\n\n return object(\n stripNulls({\n property_id: propertyId,\n date_range: {\n start_date: params.startDate,\n end_date: params.endDate,\n },\n overview: {\n total_sessions: totalSessions,\n returned_rows: landingPages.length,\n available_rows: landingReport.rowCount,\n top_landing_page: landingPages[0]?.landing_page,\n },\n landing_pages: landingPages,\n quota: extractQuotaSnapshot(landingReport),\n })\n );\n } catch (err) {\n return error(err instanceof Error ? err.message : \"Failed to fetch GA4 top landing pages\");\n }\n}\n"],
|
|
5
5
|
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAE3B,MAAM,YAAY;AAEX,MAAM,wBAAwB,EAAE,OAAO;AAAA,EAC5C,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,iCAAiC;AAAA,EACjF,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,+BAA+B;AAAA,EAC7E,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yFAAyF;AAAA,EACpI,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,uEAAuE;AAAA,EACjH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,wBAAwB;AACtF,CAAC;AAED,eAAsB,uBAAuB,QAA+C;AAC1F,MAAI;AACF,UAAM,aAAa,MAAM,qBAAqB,OAAO,YAAY,OAAO,SAAS;AACjF,UAAM,QAAQ,OAAO,SAAS;AAE9B,UAAM,CAAC,eAAe,WAAW,IAAI,MAAM,QAAQ,IAAI;AAAA,MACrD,UAAU,YAAY;AAAA,QACpB,YAAY,CAAC,EAAE,WAAW,OAAO,WAAW,SAAS,OAAO,QAAQ,CAAC;AAAA,QACrE,YAAY,CAAC,EAAE,MAAM,cAAc,CAAC;AAAA,QACpC,SAAS,CAAC,EAAE,MAAM,WAAW,GAAG,EAAE,MAAM,aAAa,CAAC;AAAA,QACtD,UAAU,CAAC,EAAE,QAAQ,EAAE,YAAY,WAAW,GAAG,MAAM,KAAK,CAAC;AAAA,QAC7D;AAAA,QACA,qBAAqB;AAAA,MACvB,CAAC;AAAA,MACD,UAAU,YAAY;AAAA,QACpB,YAAY,CAAC,EAAE,WAAW,OAAO,WAAW,SAAS,OAAO,QAAQ,CAAC;AAAA,QACrE,SAAS,CAAC,EAAE,MAAM,WAAW,GAAG,EAAE,MAAM,aAAa,CAAC;AAAA,MACxD,CAAC;AAAA,IACH,CAAC;AAED,UAAM,gBAAgB;AAAA,MACpB,YAAY,OAAO,CAAC,KAAK,CAAC;AAAA,MAC1B,YAAY;AAAA,MACZ;AAAA,IACF;AAEA,UAAM,gBAAgB,cAAc,QAAQ,CAAC,GAAG,IAAI,CAAC,QAAQ;AAC3D,YAAM,WAAW,qBAAqB,KAAK,cAAc,eAAe,UAAU;AAClF,YAAM,QAAQ,qBAAqB,KAAK,cAAc,eAAe,YAAY;AAEjF,aAAO;AAAA,QACL,cAAc,kBAAkB,GAAG;AAAA,QACnC;AAAA,QACA;AAAA,QACA,uBAAuB,MAAM,UAAU,UAAU,aAAa,CAAC;AAAA,QAC/D,YAAY,kBAAkB,GAAG,MAAM;AAAA,MACzC;AAAA,IACF,CAAC;AAED,WAAO;AAAA,MACL,WAAW;AAAA,QACT,aAAa;AAAA,QACb,YAAY;AAAA,UACV,YAAY,OAAO;AAAA,UACnB,UAAU,OAAO;AAAA,QACnB;AAAA,QACA,UAAU;AAAA,UACR,gBAAgB;AAAA,UAChB,eAAe,aAAa;AAAA,UAC5B,gBAAgB,cAAc;AAAA,UAC9B,kBAAkB,aAAa,CAAC,GAAG;AAAA,QACrC;AAAA,QACA,eAAe;AAAA,QACf,OAAO,qBAAqB,aAAa;AAAA,MAC3C,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,MAAM,eAAe,QAAQ,IAAI,UAAU,uCAAuC;AAAA,EAC3F;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/config/check-database-connection.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { checkTableExists, getDatabaseUrl, testDatabaseConnection } from \"../../db/client.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nexport const checkDatabaseConnectionSchema = z.object({});\n\nfunction getConnectionHints() {\n const databaseUrl = getDatabaseUrl();\n if (!databaseUrl) {\n return {\n database_url_present: false,\n host_hint: undefined,\n port_hint: undefined,\n };\n }\n\n try {\n const parsedUrl = new URL(databaseUrl);\n\n return {\n database_url_present: true,\n host_hint: parsedUrl.hostname || undefined,\n port_hint: parsedUrl.port || undefined,\n };\n } catch {\n return {\n database_url_present: true,\n host_hint: undefined,\n port_hint: undefined,\n };\n }\n}\n\nexport async function checkDatabaseConnectionHandler() {\n try {\n const result = await testDatabaseConnection();\n const schemaMigrationsTablePresent = await checkTableExists(\"schema_migrations\");\n const profilesTablePresent = await checkTableExists(\"profiles\");\n const profileVtexConnectionsTablePresent = await checkTableExists(\"profile_vtex_connections\");\n const hints = getConnectionHints();\n\n return object(\n stripNulls({\n status: \"ok\",\n database: result.current_database,\n user: result.current_user,\n server_time: result.now.toISOString(),\n database_url_present: hints.database_url_present,\n host_hint: hints.host_hint,\n port_hint: hints.port_hint,\n schema_migrations_table_present: schemaMigrationsTablePresent,\n profiles_table_present: profilesTablePresent,\n profile_vtex_connections_table_present: profileVtexConnectionsTablePresent,\n })\n );\n } catch (err) {\n return error(err instanceof Error ? err.message : \"Database connection check failed\");\n }\n}\n"],
|
|
5
5
|
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,kBAAkB,gBAAgB,8BAA8B;AACzE,SAAS,kBAAkB;AAEpB,MAAM,gCAAgC,EAAE,OAAO,CAAC,CAAC;AAExD,SAAS,qBAAqB;AAC5B,QAAM,cAAc,eAAe;AACnC,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,MACL,sBAAsB;AAAA,MACtB,WAAW;AAAA,MACX,WAAW;AAAA,IACb;AAAA,EACF;AAEA,MAAI;AACF,UAAM,YAAY,IAAI,IAAI,WAAW;AAErC,WAAO;AAAA,MACL,sBAAsB;AAAA,MACtB,WAAW,UAAU,YAAY;AAAA,MACjC,WAAW,UAAU,QAAQ;AAAA,IAC/B;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,MACL,sBAAsB;AAAA,MACtB,WAAW;AAAA,MACX,WAAW;AAAA,IACb;AAAA,EACF;AACF;AAEA,eAAsB,iCAAiC;AACrD,MAAI;AACF,UAAM,SAAS,MAAM,uBAAuB;AAC5C,UAAM,+BAA+B,MAAM,iBAAiB,mBAAmB;AAC/E,UAAM,uBAAuB,MAAM,iBAAiB,UAAU;AAC9D,UAAM,qCAAqC,MAAM,iBAAiB,0BAA0B;AAC5F,UAAM,QAAQ,mBAAmB;AAEjC,WAAO;AAAA,MACL,WAAW;AAAA,QACT,QAAQ;AAAA,QACR,UAAU,OAAO;AAAA,QACjB,MAAM,OAAO;AAAA,QACb,aAAa,OAAO,IAAI,YAAY;AAAA,QACpC,sBAAsB,MAAM;AAAA,QAC5B,WAAW,MAAM;AAAA,QACjB,WAAW,MAAM;AAAA,QACjB,iCAAiC;AAAA,QACjC,wBAAwB;AAAA,QACxB,wCAAwC;AAAA,MAC1C,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,MAAM,eAAe,QAAQ,IAAI,UAAU,kCAAkC;AAAA,EACtF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/config/index.ts"],
|
|
4
|
-
"sourcesContent": ["export * from \"./check-database-connection.js\";\
|
|
4
|
+
"sourcesContent": ["export * from \"./check-database-connection.js\";\nexport * from \"./list-profiles.js\";\n"],
|
|
5
5
|
"mappings": "AAAA,cAAc;AACd,cAAc;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/config/list-profiles.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from 'mcp-use/server';\
|
|
4
|
+
"sourcesContent": ["import { error, object } from 'mcp-use/server';\nimport { z } from 'zod';\nimport { listProfileGoogleServiceMappings } from '../../config/google-store.js';\nimport { listProfiles } from '../../config/profile-store.js';\n\nexport const listProfilesSchema = z.object({});\n\nexport async function listProfilesHandler() {\n try {\n const [profiles, mappings] = await Promise.all([listProfiles({ activeOnly: true }), listProfileGoogleServiceMappings()]);\n const mappingsByProfileId = new Map(mappings.map((mapping) => [mapping.profileId, mapping]));\n return object({\n total_profiles: profiles.length,\n profiles: profiles.map((profile) => {\n const mapping = mappingsByProfileId.get(profile.id);\n return {\n profile_id: profile.id,\n name: profile.name,\n is_active: profile.isActive,\n created_at: profile.createdAt.toISOString(),\n updated_at: profile.updatedAt.toISOString(),\n google_services: {\n has_google_ads: Boolean(mapping?.googleAdsCustomerId),\n has_ga4: Boolean(mapping?.ga4PropertyId),\n has_search_console: Boolean(mapping?.searchConsoleSiteUrl),\n statuses: {\n google_ads: mapping?.googleAdsCustomerId ? mapping.googleAdsStatus : 'not_configured',\n ga4: mapping?.ga4PropertyId ? mapping.ga4Status : 'not_configured',\n search_console: mapping?.searchConsoleSiteUrl ? mapping.searchConsoleStatus : 'not_configured',\n },\n },\n };\n }),\n });\n } catch (err) {\n return error(err instanceof Error ? err.message : 'Failed to list profiles');\n }\n}\n"],
|
|
5
5
|
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAClB,SAAS,wCAAwC;AACjD,SAAS,oBAAoB;AAEtB,MAAM,qBAAqB,EAAE,OAAO,CAAC,CAAC;AAE7C,eAAsB,sBAAsB;AAC1C,MAAI;AACF,UAAM,CAAC,UAAU,QAAQ,IAAI,MAAM,QAAQ,IAAI,CAAC,aAAa,EAAE,YAAY,KAAK,CAAC,GAAG,iCAAiC,CAAC,CAAC;AACvH,UAAM,sBAAsB,IAAI,IAAI,SAAS,IAAI,CAAC,YAAY,CAAC,QAAQ,WAAW,OAAO,CAAC,CAAC;AAC3F,WAAO,OAAO;AAAA,MACZ,gBAAgB,SAAS;AAAA,MACzB,UAAU,SAAS,IAAI,CAAC,YAAY;AAClC,cAAM,UAAU,oBAAoB,IAAI,QAAQ,EAAE;AAClD,eAAO;AAAA,UACL,YAAY,QAAQ;AAAA,UACpB,MAAM,QAAQ;AAAA,UACd,WAAW,QAAQ;AAAA,UACnB,YAAY,QAAQ,UAAU,YAAY;AAAA,UAC1C,YAAY,QAAQ,UAAU,YAAY;AAAA,UAC1C,iBAAiB;AAAA,YACf,gBAAgB,QAAQ,SAAS,mBAAmB;AAAA,YACpD,SAAS,QAAQ,SAAS,aAAa;AAAA,YACvC,oBAAoB,QAAQ,SAAS,oBAAoB;AAAA,YACzD,UAAU;AAAA,cACR,YAAY,SAAS,sBAAsB,QAAQ,kBAAkB;AAAA,cACrE,KAAK,SAAS,gBAAgB,QAAQ,YAAY;AAAA,cAClD,gBAAgB,SAAS,uBAAuB,QAAQ,sBAAsB;AAAA,YAChF;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,WAAO,MAAM,eAAe,QAAQ,IAAI,UAAU,yBAAyB;AAAA,EAC7E;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/google-ads/account-overview.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport {\n dateRegex,\n getFieldValue,\n microsToCurrency,\n parseGoogleAdsMetricValue,\n resolveGoogleAdsCustomerId,\n resolveGoogleAdsDeveloperToken,\n resolveGoogleAdsLoginCustomerId,\n round,\n toPercent,\n} from \"../../utils/google-ads.js\";\nimport { searchGoogleAds } from \"../../services/google-ads/google-ads-client.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nexport const googleAdsAccountOverviewSchema = z.object({\n startDate: z.string().regex(dateRegex).describe(\"Start date in YYYY-MM-DD format.\"),\n endDate: z.string().regex(dateRegex).describe(\"End date in YYYY-MM-DD format.\"),\n customerId: z.string().optional().describe(\"Google Ads customer ID to query. If omitted, resolves the profileId mapping. Accepts digits with or without hyphens.\"),\n profileId: z.string().optional().describe(\"Optional business profile ID used to resolve the mapped Google Ads customer ID.\"),\n loginCustomerId: z\n .string()\n .optional()\n .describe(\n \"Optional manager account ID used as login customer. If omitted, uses GOOGLE_ADS_LOGIN_CUSTOMER_ID when configured.\"\n ),\n});\n\nexport async function googleAdsAccountOverviewHandler(\n params: z.infer<typeof googleAdsAccountOverviewSchema>\n) {\n try {\n const customerId = await resolveGoogleAdsCustomerId(params.customerId, params.profileId);\n const loginCustomerId = resolveGoogleAdsLoginCustomerId(params.loginCustomerId);\n const developerToken = resolveGoogleAdsDeveloperToken();\n\n const result = await searchGoogleAds(\n customerId,\n [\n \"SELECT\",\n \"customer.id,\",\n \"customer.descriptive_name,\",\n \"customer.currency_code,\",\n \"customer.time_zone,\",\n \"metrics.impressions,\",\n \"metrics.clicks,\",\n \"metrics.cost_micros,\",\n \"metrics.conversions,\",\n \"metrics.conversions_value,\",\n \"metrics.ctr,\",\n \"metrics.average_cpc\",\n \"FROM customer\",\n `WHERE segments.date BETWEEN '${params.startDate}' AND '${params.endDate}'`,\n ].join(\" \"),\n developerToken,\n loginCustomerId\n );\n\n const row = result.rows[0] ?? {};\n const impressions = parseGoogleAdsMetricValue(getFieldValue(row, \"metrics.impressions\"));\n const clicks = parseGoogleAdsMetricValue(getFieldValue(row, \"metrics.clicks\"));\n const cost = microsToCurrency(getFieldValue(row, \"metrics.costMicros\"));\n const conversions = round(\n parseGoogleAdsMetricValue(getFieldValue(row, \"metrics.conversions\"))\n );\n const conversionValue = round(\n parseGoogleAdsMetricValue(getFieldValue(row, \"metrics.conversionsValue\"))\n );\n const ctrPercent = round(\n parseGoogleAdsMetricValue(getFieldValue(row, \"metrics.ctr\")) * 100\n );\n const averageCpc = microsToCurrency(getFieldValue(row, \"metrics.averageCpc\"));\n\n return object(\n stripNulls({\n customer_id: customerId,\n login_customer_id: loginCustomerId,\n date_range: {\n start_date: params.startDate,\n end_date: params.endDate,\n },\n currency_code: getFieldValue(row, \"customer.currencyCode\"),\n customer_name: getFieldValue(row, \"customer.descriptiveName\"),\n time_zone: getFieldValue(row, \"customer.timeZone\"),\n overview: {\n impressions,\n clicks,\n cost,\n conversions,\n conversion_value: conversionValue,\n ctr_percent: ctrPercent,\n average_cpc: averageCpc,\n cpa: round(cost / conversions),\n roas: round(conversionValue / cost),\n conversion_rate_percent: round(toPercent(conversions, clicks)),\n },\n metadata: {\n row_count: result.rows.length,\n request_id: result.requestId,\n },\n })\n );\n } catch (err) {\n return error(\n err instanceof Error ? err.message : \"Failed to fetch Google Ads account overview\"\n );\n }\n}\n"],
|
|
5
5
|
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,uBAAuB;AAChC,SAAS,kBAAkB;AAEpB,MAAM,iCAAiC,EAAE,OAAO;AAAA,EACrD,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,kCAAkC;AAAA,EAClF,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,gCAAgC;AAAA,EAC9E,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,sHAAsH;AAAA,EACjK,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,iFAAiF;AAAA,EAC3H,iBAAiB,EACd,OAAO,EACP,SAAS,EACT;AAAA,IACC;AAAA,EACF;AACJ,CAAC;AAED,eAAsB,gCACpB,QACA;AACA,MAAI;AACF,UAAM,aAAa,MAAM,2BAA2B,OAAO,YAAY,OAAO,SAAS;AACvF,UAAM,kBAAkB,gCAAgC,OAAO,eAAe;AAC9E,UAAM,iBAAiB,+BAA+B;AAEtD,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,gCAAgC,OAAO,SAAS,UAAU,OAAO,OAAO;AAAA,MAC1E,EAAE,KAAK,GAAG;AAAA,MACV;AAAA,MACA;AAAA,IACF;AAEA,UAAM,MAAM,OAAO,KAAK,CAAC,KAAK,CAAC;AAC/B,UAAM,cAAc,0BAA0B,cAAc,KAAK,qBAAqB,CAAC;AACvF,UAAM,SAAS,0BAA0B,cAAc,KAAK,gBAAgB,CAAC;AAC7E,UAAM,OAAO,iBAAiB,cAAc,KAAK,oBAAoB,CAAC;AACtE,UAAM,cAAc;AAAA,MAClB,0BAA0B,cAAc,KAAK,qBAAqB,CAAC;AAAA,IACrE;AACA,UAAM,kBAAkB;AAAA,MACtB,0BAA0B,cAAc,KAAK,0BAA0B,CAAC;AAAA,IAC1E;AACA,UAAM,aAAa;AAAA,MACjB,0BAA0B,cAAc,KAAK,aAAa,CAAC,IAAI;AAAA,IACjE;AACA,UAAM,aAAa,iBAAiB,cAAc,KAAK,oBAAoB,CAAC;AAE5E,WAAO;AAAA,MACL,WAAW;AAAA,QACT,aAAa;AAAA,QACb,mBAAmB;AAAA,QACnB,YAAY;AAAA,UACV,YAAY,OAAO;AAAA,UACnB,UAAU,OAAO;AAAA,QACnB;AAAA,QACA,eAAe,cAAc,KAAK,uBAAuB;AAAA,QACzD,eAAe,cAAc,KAAK,0BAA0B;AAAA,QAC5D,WAAW,cAAc,KAAK,mBAAmB;AAAA,QACjD,UAAU;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,kBAAkB;AAAA,UAClB,aAAa;AAAA,UACb,aAAa;AAAA,UACb,KAAK,MAAM,OAAO,WAAW;AAAA,UAC7B,MAAM,MAAM,kBAAkB,IAAI;AAAA,UAClC,yBAAyB,MAAM,UAAU,aAAa,MAAM,CAAC;AAAA,QAC/D;AAAA,QACA,UAAU;AAAA,UACR,WAAW,OAAO,KAAK;AAAA,UACvB,YAAY,OAAO;AAAA,QACrB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,eAAe,QAAQ,IAAI,UAAU;AAAA,IACvC;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/google-ads/account-risks.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\r\nimport { z } from \"zod\";\r\n\r\nimport {\r\n dateRegex,\r\n getFieldValue,\r\n microsToCurrency,\r\n parseGoogleAdsMetricValue,\r\n resolveGoogleAdsCustomerId,\r\n resolveGoogleAdsDeveloperToken,\r\n resolveGoogleAdsLoginCustomerId,\r\n round,\r\n toPercent,\r\n} from \"../../utils/google-ads.js\";\r\nimport { searchGoogleAds } from \"../../services/google-ads/google-ads-client.js\";\r\nimport { stripNulls } from \"../../utils/strip-payload.js\";\r\n\r\ntype RiskSeverity = \"low\" | \"medium\" | \"high\";\r\n\r\nfunction buildRisk(\r\n code: string,\r\n severity: RiskSeverity,\r\n title: string,\r\n detail: string,\r\n metricValue?: number\r\n) {\r\n return stripNulls({\r\n code,\r\n severity,\r\n title,\r\n detail,\r\n metric_value: metricValue !== undefined ? round(metricValue) : undefined,\r\n });\r\n}\r\n\r\nexport const googleAdsAccountRisksSchema = z.object({\r\n startDate: z.string().regex(dateRegex).describe(\"Start date in YYYY-MM-DD format.\"),\r\n endDate: z.string().regex(dateRegex).describe(\"End date in YYYY-MM-DD format.\"),\r\n customerId: z\r\n .string()\r\n .optional()\r\n .describe(\"Google Ads customer ID to query. If omitted, resolves the profileId mapping. Accepts digits with or without hyphens.\"),\r\n profileId: z.string().optional().describe(\"Optional business profile ID used to resolve the mapped Google Ads customer ID.\"),\r\n loginCustomerId: z\r\n .string()\r\n .optional()\r\n .describe(\r\n \"Optional manager account ID used as login customer. If omitted, uses GOOGLE_ADS_LOGIN_CUSTOMER_ID when configured.\"\r\n ),\r\n});\r\n\r\nexport async function googleAdsAccountRisksHandler(\r\n params: z.infer<typeof googleAdsAccountRisksSchema>\r\n) {\r\n try {\r\n const customerId = await resolveGoogleAdsCustomerId(params.customerId, params.profileId);\r\n const loginCustomerId = resolveGoogleAdsLoginCustomerId(params.loginCustomerId);\r\n const developerToken = resolveGoogleAdsDeveloperToken();\r\n\r\n const [campaignsResult, channelsResult, seriesResult] = await Promise.all([\r\n searchGoogleAds(\r\n customerId,\r\n [\r\n \"SELECT\",\r\n \"customer.descriptive_name,\",\r\n \"customer.currency_code,\",\r\n \"campaign.id,\",\r\n \"campaign.name,\",\r\n \"campaign.advertising_channel_type,\",\r\n \"metrics.impressions,\",\r\n \"metrics.clicks,\",\r\n \"metrics.cost_micros,\",\r\n \"metrics.conversions,\",\r\n \"metrics.conversions_value\",\r\n \"FROM campaign\",\r\n `WHERE segments.date BETWEEN '${params.startDate}' AND '${params.endDate}'`,\r\n \"AND campaign.status = 'ENABLED'\",\r\n \"ORDER BY metrics.cost_micros DESC\",\r\n ].join(\" \"),\r\n developerToken,\r\n loginCustomerId\r\n ),\r\n searchGoogleAds(\r\n customerId,\r\n [\r\n \"SELECT\",\r\n \"campaign.advertising_channel_type,\",\r\n \"metrics.cost_micros,\",\r\n \"metrics.conversions_value\",\r\n \"FROM campaign\",\r\n `WHERE segments.date BETWEEN '${params.startDate}' AND '${params.endDate}'`,\r\n \"AND campaign.status = 'ENABLED'\",\r\n ].join(\" \"),\r\n developerToken,\r\n loginCustomerId\r\n ),\r\n searchGoogleAds(\r\n customerId,\r\n [\r\n \"SELECT\",\r\n \"segments.date,\",\r\n \"metrics.cost_micros,\",\r\n \"metrics.conversions_value,\",\r\n \"metrics.conversions\",\r\n \"FROM customer\",\r\n `WHERE segments.date BETWEEN '${params.startDate}' AND '${params.endDate}'`,\r\n \"ORDER BY segments.date\",\r\n ].join(\" \"),\r\n developerToken,\r\n loginCustomerId\r\n ),\r\n ]);\r\n\r\n const campaignRows = campaignsResult.rows.map((row) => ({\r\n campaign_name: getFieldValue(row, \"campaign.name\"),\r\n channel_type: getFieldValue(row, \"campaign.advertisingChannelType\"),\r\n cost: microsToCurrency(getFieldValue(row, \"metrics.costMicros\")),\r\n conversions: round(parseGoogleAdsMetricValue(getFieldValue(row, \"metrics.conversions\"))),\r\n conversion_value: round(\r\n parseGoogleAdsMetricValue(getFieldValue(row, \"metrics.conversionsValue\"))\r\n ),\r\n }));\r\n\r\n const totalCost = campaignRows.reduce((sum, row) => sum + row.cost, 0);\r\n const totalConversions = campaignRows.reduce((sum, row) => sum + row.conversions, 0);\r\n const totalConversionValue = campaignRows.reduce((sum, row) => sum + row.conversion_value, 0);\r\n const topCampaign = campaignRows[0];\r\n const topCampaignShare = round(toPercent(topCampaign?.cost ?? 0, totalCost));\r\n\r\n const channelCosts = new Map<string, number>();\r\n for (const row of channelsResult.rows) {\r\n const channelType = String(\r\n getFieldValue(row, \"campaign.advertisingChannelType\", \"UNKNOWN\") ?? \"UNKNOWN\"\r\n );\r\n channelCosts.set(\r\n channelType,\r\n (channelCosts.get(channelType) ?? 0) +\r\n microsToCurrency(getFieldValue(row, \"metrics.costMicros\"))\r\n );\r\n }\r\n const dominantChannel = Array.from(channelCosts.entries()).sort((a, b) => b[1] - a[1])[0];\r\n const dominantChannelShare = round(toPercent(dominantChannel?.[1] ?? 0, totalCost));\r\n\r\n const series = seriesResult.rows.map((row) => ({\r\n period_start: String(getFieldValue(row, \"segments.date\") ?? \"\"),\r\n cost: microsToCurrency(getFieldValue(row, \"metrics.costMicros\")),\r\n conversion_value: round(\r\n parseGoogleAdsMetricValue(getFieldValue(row, \"metrics.conversionsValue\"))\r\n ),\r\n conversions: round(parseGoogleAdsMetricValue(getFieldValue(row, \"metrics.conversions\"))),\r\n }));\r\n const midpoint = Math.ceil(series.length / 2);\r\n const firstHalf = series.slice(0, midpoint);\r\n const secondHalf = series.slice(midpoint);\r\n const firstHalfRoas = round(\r\n firstHalf.reduce((sum, item) => sum + item.conversion_value, 0) /\r\n firstHalf.reduce((sum, item) => sum + item.cost, 0)\r\n );\r\n const secondHalfRoas = round(\r\n secondHalf.reduce((sum, item) => sum + item.conversion_value, 0) /\r\n secondHalf.reduce((sum, item) => sum + item.cost, 0)\r\n );\r\n\r\n const risks = [];\r\n\r\n if (topCampaignShare >= 70) {\r\n risks.push(\r\n buildRisk(\r\n \"campaign_concentration_high\",\r\n \"high\",\r\n \"Concentraci\u00F3n alta en una campa\u00F1a\",\r\n `La campa\u00F1a principal concentra ${topCampaignShare}% del gasto.`,\r\n topCampaignShare\r\n )\r\n );\r\n } else if (topCampaignShare >= 50) {\r\n risks.push(\r\n buildRisk(\r\n \"campaign_concentration_medium\",\r\n \"medium\",\r\n \"Concentraci\u00F3n relevante en una campa\u00F1a\",\r\n `La campa\u00F1a principal concentra ${topCampaignShare}% del gasto.`,\r\n topCampaignShare\r\n )\r\n );\r\n }\r\n\r\n if (dominantChannelShare >= 80) {\r\n risks.push(\r\n buildRisk(\r\n \"channel_concentration_high\",\r\n \"high\",\r\n \"Dependencia alta de un tipo de campa\u00F1a\",\r\n `${dominantChannel?.[0] ?? \"UNKNOWN\"} concentra ${dominantChannelShare}% del gasto.`,\r\n dominantChannelShare\r\n )\r\n );\r\n } else if (dominantChannelShare >= 60) {\r\n risks.push(\r\n buildRisk(\r\n \"channel_concentration_medium\",\r\n \"medium\",\r\n \"Dependencia relevante de un tipo de campa\u00F1a\",\r\n `${dominantChannel?.[0] ?? \"UNKNOWN\"} concentra ${dominantChannelShare}% del gasto.`,\r\n dominantChannelShare\r\n )\r\n );\r\n }\r\n\r\n const overallRoas = round(totalConversionValue / totalCost);\r\n if (overallRoas < 1) {\r\n risks.push(\r\n buildRisk(\r\n \"low_roas\",\r\n \"high\",\r\n \"ROAS por debajo de 1\",\r\n `El ROAS agregado es ${overallRoas}. La cuenta est\u00E1 devolviendo menos valor que el gasto atribuido.`,\r\n overallRoas\r\n )\r\n );\r\n } else if (overallRoas < 1.5) {\r\n risks.push(\r\n buildRisk(\r\n \"borderline_roas\",\r\n \"medium\",\r\n \"ROAS ajustado al l\u00EDmite\",\r\n `El ROAS agregado es ${overallRoas}. Hay poco margen antes de entrar en zona de riesgo.`,\r\n overallRoas\r\n )\r\n );\r\n }\r\n\r\n if (totalConversions < 5) {\r\n risks.push(\r\n buildRisk(\r\n \"low_conversion_volume\",\r\n \"medium\",\r\n \"Volumen de conversiones bajo\",\r\n `La cuenta gener\u00F3 ${round(totalConversions)} conversiones en el per\u00EDodo. La se\u00F1al estad\u00EDstica es limitada.`,\r\n totalConversions\r\n )\r\n );\r\n }\r\n\r\n if (firstHalf.length > 0 && secondHalf.length > 0 && secondHalfRoas < firstHalfRoas * 0.7) {\r\n risks.push(\r\n buildRisk(\r\n \"roas_deteriorating\",\r\n \"medium\",\r\n \"Deterioro reciente de eficiencia\",\r\n `El ROAS cay\u00F3 de ${firstHalfRoas} en la primera mitad a ${secondHalfRoas} en la segunda mitad del per\u00EDodo.`,\r\n secondHalfRoas\r\n )\r\n );\r\n }\r\n\r\n const highSeverityCount = risks.filter((risk) => risk.severity === \"high\").length;\r\n const mediumSeverityCount = risks.filter((risk) => risk.severity === \"medium\").length;\r\n const overallSeverity: RiskSeverity =\r\n highSeverityCount > 0 ? \"high\" : mediumSeverityCount > 0 ? \"medium\" : \"low\";\r\n\r\n return object(\r\n stripNulls({\r\n customer_id: customerId,\r\n login_customer_id: loginCustomerId,\r\n customer_name: getFieldValue(campaignsResult.rows[0] ?? {}, \"customer.descriptiveName\"),\r\n currency_code: getFieldValue(campaignsResult.rows[0] ?? {}, \"customer.currencyCode\"),\r\n date_range: {\r\n start_date: params.startDate,\r\n end_date: params.endDate,\r\n },\r\n overview: {\r\n total_campaigns: campaignRows.length,\r\n total_cost: round(totalCost),\r\n total_conversions: round(totalConversions),\r\n total_conversion_value: round(totalConversionValue),\r\n roas: overallRoas,\r\n top_campaign_by_cost: topCampaign?.campaign_name,\r\n top_campaign_cost_share_percent: topCampaignShare,\r\n dominant_channel: dominantChannel?.[0],\r\n dominant_channel_cost_share_percent: dominantChannelShare,\r\n first_half_roas: firstHalfRoas,\r\n second_half_roas: secondHalfRoas,\r\n },\r\n risk_summary: {\r\n overall_severity: overallSeverity,\r\n high_severity_count: highSeverityCount,\r\n medium_severity_count: mediumSeverityCount,\r\n total_risks: risks.length,\r\n },\r\n risks,\r\n metadata: {\r\n request_ids: [campaignsResult.requestId, channelsResult.requestId, seriesResult.requestId],\r\n },\r\n })\r\n );\r\n } catch (err) {\r\n return error(err instanceof Error ? err.message : \"Failed to evaluate Google Ads account risks\");\r\n }\r\n}\r\n"],
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport {\n dateRegex,\n getFieldValue,\n microsToCurrency,\n parseGoogleAdsMetricValue,\n resolveGoogleAdsCustomerId,\n resolveGoogleAdsDeveloperToken,\n resolveGoogleAdsLoginCustomerId,\n round,\n toPercent,\n} from \"../../utils/google-ads.js\";\nimport { searchGoogleAds } from \"../../services/google-ads/google-ads-client.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\ntype RiskSeverity = \"low\" | \"medium\" | \"high\";\n\nfunction buildRisk(\n code: string,\n severity: RiskSeverity,\n title: string,\n detail: string,\n metricValue?: number\n) {\n return stripNulls({\n code,\n severity,\n title,\n detail,\n metric_value: metricValue !== undefined ? round(metricValue) : undefined,\n });\n}\n\nexport const googleAdsAccountRisksSchema = z.object({\n startDate: z.string().regex(dateRegex).describe(\"Start date in YYYY-MM-DD format.\"),\n endDate: z.string().regex(dateRegex).describe(\"End date in YYYY-MM-DD format.\"),\n customerId: z\n .string()\n .optional()\n .describe(\"Google Ads customer ID to query. If omitted, resolves the profileId mapping. Accepts digits with or without hyphens.\"),\n profileId: z.string().optional().describe(\"Optional business profile ID used to resolve the mapped Google Ads customer ID.\"),\n loginCustomerId: z\n .string()\n .optional()\n .describe(\n \"Optional manager account ID used as login customer. If omitted, uses GOOGLE_ADS_LOGIN_CUSTOMER_ID when configured.\"\n ),\n});\n\nexport async function googleAdsAccountRisksHandler(\n params: z.infer<typeof googleAdsAccountRisksSchema>\n) {\n try {\n const customerId = await resolveGoogleAdsCustomerId(params.customerId, params.profileId);\n const loginCustomerId = resolveGoogleAdsLoginCustomerId(params.loginCustomerId);\n const developerToken = resolveGoogleAdsDeveloperToken();\n\n const [campaignsResult, channelsResult, seriesResult] = await Promise.all([\n searchGoogleAds(\n customerId,\n [\n \"SELECT\",\n \"customer.descriptive_name,\",\n \"customer.currency_code,\",\n \"campaign.id,\",\n \"campaign.name,\",\n \"campaign.advertising_channel_type,\",\n \"metrics.impressions,\",\n \"metrics.clicks,\",\n \"metrics.cost_micros,\",\n \"metrics.conversions,\",\n \"metrics.conversions_value\",\n \"FROM campaign\",\n `WHERE segments.date BETWEEN '${params.startDate}' AND '${params.endDate}'`,\n \"AND campaign.status = 'ENABLED'\",\n \"ORDER BY metrics.cost_micros DESC\",\n ].join(\" \"),\n developerToken,\n loginCustomerId\n ),\n searchGoogleAds(\n customerId,\n [\n \"SELECT\",\n \"campaign.advertising_channel_type,\",\n \"metrics.cost_micros,\",\n \"metrics.conversions_value\",\n \"FROM campaign\",\n `WHERE segments.date BETWEEN '${params.startDate}' AND '${params.endDate}'`,\n \"AND campaign.status = 'ENABLED'\",\n ].join(\" \"),\n developerToken,\n loginCustomerId\n ),\n searchGoogleAds(\n customerId,\n [\n \"SELECT\",\n \"segments.date,\",\n \"metrics.cost_micros,\",\n \"metrics.conversions_value,\",\n \"metrics.conversions\",\n \"FROM customer\",\n `WHERE segments.date BETWEEN '${params.startDate}' AND '${params.endDate}'`,\n \"ORDER BY segments.date\",\n ].join(\" \"),\n developerToken,\n loginCustomerId\n ),\n ]);\n\n const campaignRows = campaignsResult.rows.map((row) => ({\n campaign_name: getFieldValue(row, \"campaign.name\"),\n channel_type: getFieldValue(row, \"campaign.advertisingChannelType\"),\n cost: microsToCurrency(getFieldValue(row, \"metrics.costMicros\")),\n conversions: round(parseGoogleAdsMetricValue(getFieldValue(row, \"metrics.conversions\"))),\n conversion_value: round(\n parseGoogleAdsMetricValue(getFieldValue(row, \"metrics.conversionsValue\"))\n ),\n }));\n\n const totalCost = campaignRows.reduce((sum, row) => sum + row.cost, 0);\n const totalConversions = campaignRows.reduce((sum, row) => sum + row.conversions, 0);\n const totalConversionValue = campaignRows.reduce((sum, row) => sum + row.conversion_value, 0);\n const topCampaign = campaignRows[0];\n const topCampaignShare = round(toPercent(topCampaign?.cost ?? 0, totalCost));\n\n const channelCosts = new Map<string, number>();\n for (const row of channelsResult.rows) {\n const channelType = String(\n getFieldValue(row, \"campaign.advertisingChannelType\", \"UNKNOWN\") ?? \"UNKNOWN\"\n );\n channelCosts.set(\n channelType,\n (channelCosts.get(channelType) ?? 0) +\n microsToCurrency(getFieldValue(row, \"metrics.costMicros\"))\n );\n }\n const dominantChannel = Array.from(channelCosts.entries()).sort((a, b) => b[1] - a[1])[0];\n const dominantChannelShare = round(toPercent(dominantChannel?.[1] ?? 0, totalCost));\n\n const series = seriesResult.rows.map((row) => ({\n period_start: String(getFieldValue(row, \"segments.date\") ?? \"\"),\n cost: microsToCurrency(getFieldValue(row, \"metrics.costMicros\")),\n conversion_value: round(\n parseGoogleAdsMetricValue(getFieldValue(row, \"metrics.conversionsValue\"))\n ),\n conversions: round(parseGoogleAdsMetricValue(getFieldValue(row, \"metrics.conversions\"))),\n }));\n const midpoint = Math.ceil(series.length / 2);\n const firstHalf = series.slice(0, midpoint);\n const secondHalf = series.slice(midpoint);\n const firstHalfRoas = round(\n firstHalf.reduce((sum, item) => sum + item.conversion_value, 0) /\n firstHalf.reduce((sum, item) => sum + item.cost, 0)\n );\n const secondHalfRoas = round(\n secondHalf.reduce((sum, item) => sum + item.conversion_value, 0) /\n secondHalf.reduce((sum, item) => sum + item.cost, 0)\n );\n\n const risks = [];\n\n if (topCampaignShare >= 70) {\n risks.push(\n buildRisk(\n \"campaign_concentration_high\",\n \"high\",\n \"Concentraci\u00F3n alta en una campa\u00F1a\",\n `La campa\u00F1a principal concentra ${topCampaignShare}% del gasto.`,\n topCampaignShare\n )\n );\n } else if (topCampaignShare >= 50) {\n risks.push(\n buildRisk(\n \"campaign_concentration_medium\",\n \"medium\",\n \"Concentraci\u00F3n relevante en una campa\u00F1a\",\n `La campa\u00F1a principal concentra ${topCampaignShare}% del gasto.`,\n topCampaignShare\n )\n );\n }\n\n if (dominantChannelShare >= 80) {\n risks.push(\n buildRisk(\n \"channel_concentration_high\",\n \"high\",\n \"Dependencia alta de un tipo de campa\u00F1a\",\n `${dominantChannel?.[0] ?? \"UNKNOWN\"} concentra ${dominantChannelShare}% del gasto.`,\n dominantChannelShare\n )\n );\n } else if (dominantChannelShare >= 60) {\n risks.push(\n buildRisk(\n \"channel_concentration_medium\",\n \"medium\",\n \"Dependencia relevante de un tipo de campa\u00F1a\",\n `${dominantChannel?.[0] ?? \"UNKNOWN\"} concentra ${dominantChannelShare}% del gasto.`,\n dominantChannelShare\n )\n );\n }\n\n const overallRoas = round(totalConversionValue / totalCost);\n if (overallRoas < 1) {\n risks.push(\n buildRisk(\n \"low_roas\",\n \"high\",\n \"ROAS por debajo de 1\",\n `El ROAS agregado es ${overallRoas}. La cuenta est\u00E1 devolviendo menos valor que el gasto atribuido.`,\n overallRoas\n )\n );\n } else if (overallRoas < 1.5) {\n risks.push(\n buildRisk(\n \"borderline_roas\",\n \"medium\",\n \"ROAS ajustado al l\u00EDmite\",\n `El ROAS agregado es ${overallRoas}. Hay poco margen antes de entrar en zona de riesgo.`,\n overallRoas\n )\n );\n }\n\n if (totalConversions < 5) {\n risks.push(\n buildRisk(\n \"low_conversion_volume\",\n \"medium\",\n \"Volumen de conversiones bajo\",\n `La cuenta gener\u00F3 ${round(totalConversions)} conversiones en el per\u00EDodo. La se\u00F1al estad\u00EDstica es limitada.`,\n totalConversions\n )\n );\n }\n\n if (firstHalf.length > 0 && secondHalf.length > 0 && secondHalfRoas < firstHalfRoas * 0.7) {\n risks.push(\n buildRisk(\n \"roas_deteriorating\",\n \"medium\",\n \"Deterioro reciente de eficiencia\",\n `El ROAS cay\u00F3 de ${firstHalfRoas} en la primera mitad a ${secondHalfRoas} en la segunda mitad del per\u00EDodo.`,\n secondHalfRoas\n )\n );\n }\n\n const highSeverityCount = risks.filter((risk) => risk.severity === \"high\").length;\n const mediumSeverityCount = risks.filter((risk) => risk.severity === \"medium\").length;\n const overallSeverity: RiskSeverity =\n highSeverityCount > 0 ? \"high\" : mediumSeverityCount > 0 ? \"medium\" : \"low\";\n\n return object(\n stripNulls({\n customer_id: customerId,\n login_customer_id: loginCustomerId,\n customer_name: getFieldValue(campaignsResult.rows[0] ?? {}, \"customer.descriptiveName\"),\n currency_code: getFieldValue(campaignsResult.rows[0] ?? {}, \"customer.currencyCode\"),\n date_range: {\n start_date: params.startDate,\n end_date: params.endDate,\n },\n overview: {\n total_campaigns: campaignRows.length,\n total_cost: round(totalCost),\n total_conversions: round(totalConversions),\n total_conversion_value: round(totalConversionValue),\n roas: overallRoas,\n top_campaign_by_cost: topCampaign?.campaign_name,\n top_campaign_cost_share_percent: topCampaignShare,\n dominant_channel: dominantChannel?.[0],\n dominant_channel_cost_share_percent: dominantChannelShare,\n first_half_roas: firstHalfRoas,\n second_half_roas: secondHalfRoas,\n },\n risk_summary: {\n overall_severity: overallSeverity,\n high_severity_count: highSeverityCount,\n medium_severity_count: mediumSeverityCount,\n total_risks: risks.length,\n },\n risks,\n metadata: {\n request_ids: [campaignsResult.requestId, channelsResult.requestId, seriesResult.requestId],\n },\n })\n );\n } catch (err) {\n return error(err instanceof Error ? err.message : \"Failed to evaluate Google Ads account risks\");\n }\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|