{"_id":"@akson/cortex-api-google-ads","_rev":"2-250533b65ae45cc63b63985bee1ef5a5","name":"@akson/cortex-api-google-ads","dist-tags":{"latest":"2.0.0"},"versions":{"2.0.0":{"name":"@akson/cortex-api-google-ads","version":"2.0.0","keywords":["google-ads","analytics","advertising","mcp","model-context-protocol","myarmy"],"author":{"name":"MyArmy","email":"contact@myarmy.ch"},"license":"MIT","_id":"@akson/cortex-api-google-ads@2.0.0","maintainers":[{"name":"antoineschaller","email":"antoine.schaller@akson.ch"}],"homepage":"https://github.com/antoineschaller/myarmy/tree/main/packages/@akson/cortex-api-google-ads","bugs":{"url":"https://github.com/antoineschaller/myarmy/issues"},"bin":{"akson-google-ads-mcp":"dist/mcp-cli.js"},"dist":{"shasum":"ed1627fa7f4995b054df1eeb2cdf5c69e5968bb5","tarball":"https://registry.npmjs.org/@akson/cortex-api-google-ads/-/cortex-api-google-ads-2.0.0.tgz","fileCount":2,"integrity":"sha512-HVdXKh+8BT1ADgYE34blnLYJz2sdRuZ+YGdsYn0KwqKD+ZDx0Nyr5Mo5GsZjtuDi+YFtA6LZvoNO/U8snJ3orQ==","signatures":[{"sig":"MEQCIHfWZvMJ3EqMEwqUo5MCAJBqeXsje2OEDo3iCOdXNaANAiAzn7TIZ/HVYiY5/W5BM4rr5ucCHl12gtTKqcHoL4UFOg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":16335},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"84153813d2b6cc183f00f23d04cf0e887c512fbe","scripts":{"dev":"tsup --watch","lint":"biome check src/","test":"vitest","build":"tsup","clean":"rm -rf dist","type-check":"tsc --noEmit"},"_npmUser":{"name":"antoineschaller","email":"antoine.schaller@akson.ch"},"repository":{"url":"git+https://github.com/antoineschaller/myarmy.git","type":"git","directory":"packages/@akson/cortex-api-google-ads"},"_npmVersion":"11.5.1","description":"Google Ads API client and MCP server for MyArmy","directories":{},"_nodeVersion":"24.7.0","dependencies":{"zod":"^3.24.1","googleapis":"^144.0.0","google-ads-api":"^14.1.0","google-auth-library":"^9.15.0","@akson/cortex-api-shared":"^0.3.0","@modelcontextprotocol/sdk":"^0.6.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.2.4","vitest":"^2.1.8","typescript":"^5.2.2","@biomejs/biome":"^1.8.3"},"_npmOperationalInternal":{"tmp":"tmp/cortex-api-google-ads_2.0.0_1757682759909_0.8790783100764323","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Package renamed to @akson/cortex-google-ads. Please update your dependencies to use the new package name."}},"time":{"created":"2025-09-12T13:12:39.829Z","modified":"2025-09-13T10:30:24.085Z","2.0.0":"2025-09-12T13:12:40.118Z"},"bugs":{"url":"https://github.com/antoineschaller/myarmy/issues"},"author":{"name":"MyArmy","email":"contact@myarmy.ch"},"license":"MIT","homepage":"https://github.com/antoineschaller/myarmy/tree/main/packages/@akson/cortex-api-google-ads","keywords":["google-ads","analytics","advertising","mcp","model-context-protocol","myarmy"],"repository":{"url":"git+https://github.com/antoineschaller/myarmy.git","type":"git","directory":"packages/@akson/cortex-api-google-ads"},"description":"Google Ads API client and MCP server for MyArmy","maintainers":[{"name":"antoineschaller","email":"antoine.schaller@akson.ch"}],"readme":"# @akson/cortex-api-google-ads\n\nTypeScript client for Google Ads API operations, enabling programmatic campaign management, conversion tracking, audience targeting, and performance optimization.\n\n## User Stories\n\n### Account & Customer Management Stories\n\n**As a PPC Account Manager**, I want to retrieve customer account information, so that I can audit account settings and permissions programmatically.\n\n**As a Digital Marketing Director**, I want to list all accessible customer accounts, so that I can manage multiple client accounts efficiently.\n\n**As a Marketing Operations Specialist**, I want to validate account access permissions, so that I can ensure API integration has required access levels.\n\n### Campaign Management Stories\n\n**As a Performance Marketing Manager**, I want to list all campaigns with their performance metrics, so that I can identify optimization opportunities at scale.\n\n**As a SEM Specialist**, I want to create new campaigns programmatically, so that I can rapidly deploy campaign structures across multiple accounts.\n\n**As a Campaign Manager**, I want to update campaign budgets and bidding strategies, so that I can respond to performance changes automatically.\n\n**As a Digital Marketing Analyst**, I want to pause or activate campaigns based on performance thresholds, so that I can prevent budget waste on underperforming campaigns.\n\n### Conversion Tracking Stories\n\n**As a Growth Marketing Manager**, I want to create conversion actions programmatically, so that I can scale attribution tracking across multiple touchpoints.\n\n**As a Marketing Attribution Specialist**, I want to list all existing conversion actions, so that I can audit current tracking implementation.\n\n**As a Performance Marketing Director**, I want to upload offline conversions, so that I can attribute phone calls and in-store purchases to digital campaigns.\n\n**As a Ecommerce Marketing Manager**, I want to bulk upload conversion data with customer information, so that I can improve audience targeting with first-party data.\n\n### Audience & Targeting Stories\n\n**As a Customer Acquisition Manager**, I want to create customer match audiences, so that I can target similar users for lookalike campaigns.\n\n**As a Retention Marketing Specialist**, I want to create remarketing audiences based on website behavior, so that I can re-engage users who didn't convert.\n\n**As a Data-Driven Marketing Manager**, I want to sync CRM data to Google Ads audiences, so that I can create highly targeted campaigns based on customer lifetime value.\n\n### Reporting & Analytics Stories\n\n**As a Marketing Analyst**, I want to execute custom GAQL queries, so that I can extract specific performance data for analysis.\n\n**As a Performance Marketing Director**, I want to generate automated reports on campaign performance, so that I can monitor ROI across all accounts.\n\n**As a Digital Marketing Manager**, I want to track impression share and competitive metrics, so that I can adjust bidding strategies to maintain market position.\n\n**As a Marketing Data Analyst**, I want to export detailed conversion path data, so that I can understand multi-touch attribution patterns.\n\n### Optimization & Automation Stories\n\n**As a SEM Manager**, I want to automatically adjust bids based on performance metrics, so that I can maximize ROAS without manual intervention.\n\n**As a Performance Marketing Specialist**, I want to create and manage responsive search ads at scale, so that I can test ad variations efficiently.\n\n**As a Growth Marketing Engineer**, I want to integrate Google Ads with marketing automation platforms, so that I can trigger campaign optimizations based on external data.\n\n### Quality & Compliance Stories\n\n**As a Compliance Manager**, I want to audit ad disapprovals and policy violations, so that I can maintain account health across all campaigns.\n\n**As a Marketing Operations Manager**, I want to validate ad creative compliance before deployment, so that I can prevent policy violations.\n\n**As a Brand Marketing Manager**, I want to monitor brand safety metrics and negative keywords, so that I can protect brand reputation in search campaigns.\n\n### Multi-Account Management Stories\n\n**As an Agency Account Director**, I want to manage multiple client accounts through a single interface, so that I can scale operations efficiently.\n\n**As a Marketing Technology Manager**, I want to synchronize campaigns across multiple Google Ads accounts, so that I can maintain consistency for multi-brand companies.\n\n**As a Digital Marketing Consultant**, I want to benchmark performance across different client accounts, so that I can identify best practices and optimization opportunities.\n\n## Installation\n\n```bash\nnpm install @akson/cortex-api-google-ads\n```\n\n## Quick Start\n\n```typescript\nimport { GoogleAdsClient } from '@akson/cortex-api-google-ads';\n\nconst client = new GoogleAdsClient({\n  config: {\n    customerId: '123-456-7890',\n    serviceAccount: {\n      keyFile: 'path/to/service-account.json',\n      email: 'ads-service@project.iam.gserviceaccount.com'\n    }\n  }\n});\n\n// Authenticate and get customer info\nawait client.authenticate();\nconst customer = await client.getCustomer();\n\n// List campaigns with performance metrics\nconst campaigns = await client.listCampaigns();\n\n// Create conversion action\nawait client.createConversionAction({\n  name: 'Website Purchase',\n  type: 'WEBPAGE',\n  category: 'PURCHASE',\n  value: 100.0,\n  currency: 'USD'\n});\n\n// Upload conversion\nawait client.uploadConversion({\n  conversionActionResourceName: 'customers/123456/conversionActions/456789',\n  gclid: 'gclid_value',\n  conversionValue: 99.99,\n  conversionDateTime: new Date().toISOString(),\n  currencyCode: 'USD'\n});\n```\n\n## Configuration\n\n### Environment Variables\n\n```bash\nGOOGLE_ADS_CUSTOMER_ID=123-456-7890\nGOOGLE_ADS_DEVELOPER_TOKEN=your-developer-token\nGOOGLE_ADS_SERVICE_ACCOUNT_EMAIL=ads-service@project.iam.gserviceaccount.com\nGOOGLE_ADS_SERVICE_ACCOUNT_KEY_FILE=path/to/key.json\n```\n\n### Configuration File\n\nCreate `google-ads-config.json`:\n\n```json\n{\n  \"customerId\": \"123-456-7890\",\n  \"developerToken\": \"your-developer-token\",\n  \"serviceAccount\": {\n    \"email\": \"ads-service@project.iam.gserviceaccount.com\",\n    \"keyFile\": \"path/to/service-account.json\"\n  }\n}\n```\n\n## API Reference\n\n### Authentication\n\n```typescript\n// Authenticate with service account\nconst authResult = await client.authenticate();\nif (!authResult.success) {\n  throw new Error(authResult.error);\n}\n```\n\n### Customer Operations\n\n```typescript\n// Get customer information\nconst customerResult = await client.getCustomer();\nif (customerResult.success) {\n  console.log('Customer:', customerResult.data);\n}\n\n// Get customer with specific ID\nconst specificCustomer = await client.getCustomer('987-654-3210');\n```\n\n### Campaign Operations\n\n```typescript\n// List all campaigns\nconst campaignsResult = await client.listCampaigns();\nif (campaignsResult.success) {\n  campaignsResult.data.forEach(campaign => {\n    console.log(`Campaign: ${campaign.name}, Status: ${campaign.status}`);\n  });\n}\n\n// Get campaign performance\nconst performance = await client.getCampaignPerformance('campaign-id', {\n  startDate: '2025-01-01',\n  endDate: '2025-01-31',\n  metrics: ['clicks', 'impressions', 'conversions', 'cost']\n});\n```\n\n### Conversion Operations\n\n```typescript\n// List conversion actions\nconst conversionsResult = await client.listConversionActions();\n\n// Create conversion action\nconst conversionResult = await client.createConversionAction({\n  name: 'Email Signup',\n  type: 'WEBPAGE',\n  category: 'SIGNUP',\n  value: 10.0,\n  currency: 'USD',\n  countingType: 'ONE_PER_CLICK'\n});\n\n// Upload single conversion\nawait client.uploadConversion({\n  conversionActionResourceName: 'customers/123/conversionActions/456',\n  gclid: 'Cj0KCQjw...',\n  conversionValue: 25.99,\n  conversionDateTime: '2025-01-15T10:30:00+00:00',\n  currencyCode: 'USD'\n});\n\n// Bulk upload conversions\nawait client.bulkUploadConversions([\n  {\n    conversionActionResourceName: 'customers/123/conversionActions/456',\n    gclid: 'Cj0KCQjw1...',\n    conversionValue: 99.99,\n    conversionDateTime: '2025-01-15T14:20:00+00:00',\n    currencyCode: 'USD'\n  },\n  {\n    conversionActionResourceName: 'customers/123/conversionActions/456',\n    gclid: 'Cj0KCQjw2...',\n    conversionValue: 149.99,\n    conversionDateTime: '2025-01-15T16:45:00+00:00',\n    currencyCode: 'USD'\n  }\n]);\n```\n\n### Query Operations\n\n```typescript\n// Execute GAQL query\nconst queryResult = await client.executeQuery({\n  query: `\n    SELECT \n      campaign.name,\n      campaign.status,\n      metrics.clicks,\n      metrics.impressions,\n      metrics.cost_micros\n    FROM campaign \n    WHERE campaign.status = 'ENABLED'\n      AND segments.date DURING LAST_30_DAYS\n    ORDER BY metrics.clicks DESC\n    LIMIT 10\n  `\n});\n\n// Query with date range\nconst dateRangeQuery = await client.executeQuery({\n  query: 'SELECT campaign.name, metrics.clicks FROM campaign',\n  customerId: '123-456-7890',\n  dateRange: {\n    startDate: '2025-01-01',\n    endDate: '2025-01-31'\n  }\n});\n```\n\n### Reporting\n\n```typescript\n// Generate campaign performance report\nconst report = await client.generateReport({\n  reportType: 'CAMPAIGN_PERFORMANCE',\n  dateRange: {\n    startDate: '2025-01-01',\n    endDate: '2025-01-31'\n  },\n  metrics: ['clicks', 'impressions', 'conversions', 'cost'],\n  dimensions: ['campaign_name', 'date'],\n  filters: {\n    campaignStatus: 'ENABLED'\n  }\n});\n\n// Export report to CSV\nawait client.exportReportToCSV(report, 'campaign-report.csv');\n```\n\n### Audience Operations\n\n```typescript\n// Create customer match audience\nconst audienceResult = await client.createCustomerMatchAudience({\n  name: 'VIP Customers',\n  description: 'High-value repeat customers',\n  membershipLifespan: 365,\n  uploadKeyType: 'EMAIL_HASH'\n});\n\n// Upload audience members\nawait client.uploadAudienceMembers(audienceResult.data.resourceName, [\n  { hashedEmail: 'hashed_email_1' },\n  { hashedEmail: 'hashed_email_2' }\n]);\n```\n\n## Error Handling\n\nAll methods return `GoogleAdsOperationResult<T>`:\n\n```typescript\nconst result = await client.listCampaigns();\n\nif (result.success) {\n  console.log('Campaigns:', result.data);\n  console.log('Total:', result.total);\n} else {\n  console.error('Error:', result.error);\n  if (result.details) {\n    console.error('Details:', result.details);\n  }\n}\n```\n\n## Advanced Usage\n\n### Performance Monitoring\n\n```typescript\nclass GoogleAdsMonitor {\n  constructor(private client: GoogleAdsClient) {}\n\n  async checkCampaignHealth() {\n    const campaigns = await this.client.listCampaigns();\n    \n    if (!campaigns.success) return;\n\n    for (const campaign of campaigns.data) {\n      const performance = await this.client.getCampaignPerformance(campaign.id, {\n        startDate: '2025-01-01',\n        endDate: new Date().toISOString().split('T')[0]\n      });\n\n      if (performance.success) {\n        const ctr = performance.data.clicks / performance.data.impressions;\n        if (ctr < 0.01) { // CTR below 1%\n          console.warn(`Low CTR alert: ${campaign.name} - ${(ctr * 100).toFixed(2)}%`);\n        }\n      }\n    }\n  }\n}\n```\n\n### Automated Bid Management\n\n```typescript\nasync function optimizeBids() {\n  const campaigns = await client.listCampaigns();\n  \n  if (!campaigns.success) return;\n\n  for (const campaign of campaigns.data) {\n    const performance = await client.getCampaignPerformance(campaign.id, {\n      startDate: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],\n      endDate: new Date().toISOString().split('T')[0]\n    });\n\n    if (performance.success) {\n      const roas = performance.data.conversionValue / (performance.data.cost / 1000000);\n      \n      if (roas > 4.0) {\n        // Increase budget by 10%\n        await client.updateCampaignBudget(campaign.id, campaign.budget * 1.1);\n        console.log(`Increased budget for high-performing campaign: ${campaign.name}`);\n      } else if (roas < 2.0) {\n        // Decrease budget by 10%\n        await client.updateCampaignBudget(campaign.id, campaign.budget * 0.9);\n        console.log(`Decreased budget for low-performing campaign: ${campaign.name}`);\n      }\n    }\n  }\n}\n```\n\n### Multi-Account Management\n\n```typescript\nclass MultiAccountManager {\n  private clients: Map<string, GoogleAdsClient> = new Map();\n\n  addClient(customerId: string, client: GoogleAdsClient) {\n    this.clients.set(customerId, client);\n  }\n\n  async getCrossAccountPerformance() {\n    const allPerformance = [];\n\n    for (const [customerId, client] of this.clients) {\n      const campaigns = await client.listCampaigns();\n      if (campaigns.success) {\n        allPerformance.push({\n          customerId,\n          campaigns: campaigns.data.length,\n          totalCost: campaigns.data.reduce((sum, c) => sum + (c.cost || 0), 0)\n        });\n      }\n    }\n\n    return allPerformance;\n  }\n}\n```\n\n## Integration Examples\n\n### Webhook-Triggered Optimizations\n\n```typescript\nimport express from 'express';\n\nconst app = express();\n\napp.post('/optimize-campaigns', async (req, res) => {\n  const { customerId, threshold } = req.body;\n  \n  const client = new GoogleAdsClient({\n    config: { customerId }\n  });\n\n  await client.authenticate();\n  \n  // Get underperforming campaigns\n  const campaigns = await client.executeQuery({\n    query: `\n      SELECT campaign.id, campaign.name, metrics.cost_per_conversion\n      FROM campaign\n      WHERE metrics.cost_per_conversion > ${threshold}\n        AND segments.date DURING LAST_7_DAYS\n    `\n  });\n\n  if (campaigns.success) {\n    for (const campaign of campaigns.data) {\n      await client.pauseCampaign(campaign.id);\n      console.log(`Paused expensive campaign: ${campaign.name}`);\n    }\n  }\n\n  res.json({ success: true, paused: campaigns.data?.length || 0 });\n});\n```\n\n### CRM Integration\n\n```typescript\nasync function syncCRMConversions() {\n  // Fetch conversions from CRM\n  const crmConversions = await fetchFromCRM();\n  \n  const conversions = crmConversions.map(crm => ({\n    conversionActionResourceName: 'customers/123/conversionActions/456',\n    gclid: crm.gclid,\n    conversionValue: crm.orderValue,\n    conversionDateTime: crm.purchaseDate,\n    currencyCode: 'USD',\n    orderId: crm.orderId\n  }));\n\n  await client.bulkUploadConversions(conversions);\n  console.log(`Uploaded ${conversions.length} CRM conversions`);\n}\n```\n\n## TypeScript Support\n\nFull TypeScript definitions included:\n\n```typescript\nimport type {\n  GoogleAdsCustomer,\n  GoogleAdsCampaign,\n  GoogleAdsConversionAction,\n  ConversionUpload,\n  GoogleAdsQuery,\n  GoogleAdsReport,\n  ReportOptions,\n  GoogleAdsOperationResult,\n  GoogleAdsListResult\n} from '@akson/cortex-api-google-ads';\n```\n\n## Requirements\n\n- Node.js ≥18.0.0\n- Google Ads API access and developer token\n- Service account with Google Ads API permissions\n- Valid Google Ads customer account\n\n## License\n\nMIT","readmeFilename":"README.md"}