@miranda0808/maya-codex 0.1.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.
Files changed (270) hide show
  1. package/README.md +30 -0
  2. package/bin/maya-codex.js +36 -0
  3. package/package.json +19 -0
  4. package/payload/.agents/skills/ab-test-setup/SKILL.md +266 -0
  5. package/payload/.agents/skills/ab-test-setup/evals/evals.json +105 -0
  6. package/payload/.agents/skills/ab-test-setup/references/sample-size-guide.md +263 -0
  7. package/payload/.agents/skills/ab-test-setup/references/test-templates.md +277 -0
  8. package/payload/.agents/skills/ad-creative/SKILL.md +362 -0
  9. package/payload/.agents/skills/ad-creative/evals/evals.json +90 -0
  10. package/payload/.agents/skills/ad-creative/references/generative-tools.md +637 -0
  11. package/payload/.agents/skills/ad-creative/references/platform-specs.md +213 -0
  12. package/payload/.agents/skills/ai-seo/SKILL.md +398 -0
  13. package/payload/.agents/skills/ai-seo/evals/evals.json +90 -0
  14. package/payload/.agents/skills/ai-seo/references/content-patterns.md +285 -0
  15. package/payload/.agents/skills/ai-seo/references/platform-ranking-factors.md +152 -0
  16. package/payload/.agents/skills/analytics-tracking/SKILL.md +309 -0
  17. package/payload/.agents/skills/analytics-tracking/evals/evals.json +90 -0
  18. package/payload/.agents/skills/analytics-tracking/references/event-library.md +260 -0
  19. package/payload/.agents/skills/analytics-tracking/references/ga4-implementation.md +300 -0
  20. package/payload/.agents/skills/analytics-tracking/references/gtm-implementation.md +390 -0
  21. package/payload/.agents/skills/churn-prevention/SKILL.md +424 -0
  22. package/payload/.agents/skills/churn-prevention/evals/evals.json +93 -0
  23. package/payload/.agents/skills/churn-prevention/references/cancel-flow-patterns.md +316 -0
  24. package/payload/.agents/skills/churn-prevention/references/dunning-playbook.md +408 -0
  25. package/payload/.agents/skills/cold-email/SKILL.md +158 -0
  26. package/payload/.agents/skills/cold-email/evals/evals.json +94 -0
  27. package/payload/.agents/skills/cold-email/references/benchmarks.md +83 -0
  28. package/payload/.agents/skills/cold-email/references/follow-up-sequences.md +81 -0
  29. package/payload/.agents/skills/cold-email/references/frameworks.md +90 -0
  30. package/payload/.agents/skills/cold-email/references/personalization.md +79 -0
  31. package/payload/.agents/skills/cold-email/references/subject-lines.md +53 -0
  32. package/payload/.agents/skills/competitor-alternatives/SKILL.md +256 -0
  33. package/payload/.agents/skills/competitor-alternatives/evals/evals.json +93 -0
  34. package/payload/.agents/skills/competitor-alternatives/references/content-architecture.md +271 -0
  35. package/payload/.agents/skills/competitor-alternatives/references/templates.md +223 -0
  36. package/payload/.agents/skills/content-strategy/SKILL.md +359 -0
  37. package/payload/.agents/skills/content-strategy/evals/evals.json +90 -0
  38. package/payload/.agents/skills/copy-editing/SKILL.md +447 -0
  39. package/payload/.agents/skills/copy-editing/evals/evals.json +89 -0
  40. package/payload/.agents/skills/copy-editing/references/plain-english-alternatives.md +394 -0
  41. package/payload/.agents/skills/copywriting/SKILL.md +252 -0
  42. package/payload/.agents/skills/copywriting/evals/evals.json +111 -0
  43. package/payload/.agents/skills/copywriting/references/copy-frameworks.md +344 -0
  44. package/payload/.agents/skills/copywriting/references/natural-transitions.md +272 -0
  45. package/payload/.agents/skills/email-sequence/SKILL.md +309 -0
  46. package/payload/.agents/skills/email-sequence/evals/evals.json +93 -0
  47. package/payload/.agents/skills/email-sequence/references/copy-guidelines.md +113 -0
  48. package/payload/.agents/skills/email-sequence/references/email-types.md +515 -0
  49. package/payload/.agents/skills/email-sequence/references/sequence-templates.md +168 -0
  50. package/payload/.agents/skills/form-cro/SKILL.md +429 -0
  51. package/payload/.agents/skills/form-cro/evals/evals.json +90 -0
  52. package/payload/.agents/skills/free-tool-strategy/SKILL.md +178 -0
  53. package/payload/.agents/skills/free-tool-strategy/evals/evals.json +90 -0
  54. package/payload/.agents/skills/free-tool-strategy/references/tool-types.md +217 -0
  55. package/payload/.agents/skills/launch-strategy/SKILL.md +353 -0
  56. package/payload/.agents/skills/launch-strategy/evals/evals.json +91 -0
  57. package/payload/.agents/skills/marketing-ideas/SKILL.md +167 -0
  58. package/payload/.agents/skills/marketing-ideas/evals/evals.json +90 -0
  59. package/payload/.agents/skills/marketing-ideas/references/ideas-by-category.md +366 -0
  60. package/payload/.agents/skills/marketing-psychology/SKILL.md +455 -0
  61. package/payload/.agents/skills/marketing-psychology/evals/evals.json +88 -0
  62. package/payload/.agents/skills/onboarding-cro/SKILL.md +220 -0
  63. package/payload/.agents/skills/onboarding-cro/evals/evals.json +92 -0
  64. package/payload/.agents/skills/onboarding-cro/references/experiments.md +258 -0
  65. package/payload/.agents/skills/page-cro/SKILL.md +182 -0
  66. package/payload/.agents/skills/page-cro/evals/evals.json +111 -0
  67. package/payload/.agents/skills/page-cro/references/experiments.md +248 -0
  68. package/payload/.agents/skills/paid-ads/SKILL.md +315 -0
  69. package/payload/.agents/skills/paid-ads/evals/evals.json +90 -0
  70. package/payload/.agents/skills/paid-ads/references/ad-copy-templates.md +207 -0
  71. package/payload/.agents/skills/paid-ads/references/audience-targeting.md +243 -0
  72. package/payload/.agents/skills/paid-ads/references/platform-setup-checklists.md +277 -0
  73. package/payload/.agents/skills/paywall-upgrade-cro/SKILL.md +227 -0
  74. package/payload/.agents/skills/paywall-upgrade-cro/evals/evals.json +93 -0
  75. package/payload/.agents/skills/paywall-upgrade-cro/references/experiments.md +164 -0
  76. package/payload/.agents/skills/popup-cro/SKILL.md +453 -0
  77. package/payload/.agents/skills/popup-cro/evals/evals.json +94 -0
  78. package/payload/.agents/skills/pricing-strategy/SKILL.md +231 -0
  79. package/payload/.agents/skills/pricing-strategy/evals/evals.json +90 -0
  80. package/payload/.agents/skills/pricing-strategy/references/research-methods.md +152 -0
  81. package/payload/.agents/skills/pricing-strategy/references/tier-structure.md +232 -0
  82. package/payload/.agents/skills/product-marketing-context/SKILL.md +27 -0
  83. package/payload/.agents/skills/product-marketing-context/evals/evals.json +40 -0
  84. package/payload/.agents/skills/programmatic-seo/SKILL.md +238 -0
  85. package/payload/.agents/skills/programmatic-seo/evals/evals.json +94 -0
  86. package/payload/.agents/skills/programmatic-seo/references/playbooks.md +308 -0
  87. package/payload/.agents/skills/referral-program/SKILL.md +255 -0
  88. package/payload/.agents/skills/referral-program/evals/evals.json +89 -0
  89. package/payload/.agents/skills/referral-program/references/affiliate-programs.md +164 -0
  90. package/payload/.agents/skills/referral-program/references/program-examples.md +143 -0
  91. package/payload/.agents/skills/revops/SKILL.md +343 -0
  92. package/payload/.agents/skills/revops/evals/evals.json +91 -0
  93. package/payload/.agents/skills/revops/references/automation-playbooks.md +290 -0
  94. package/payload/.agents/skills/revops/references/lifecycle-definitions.md +278 -0
  95. package/payload/.agents/skills/revops/references/routing-rules.md +203 -0
  96. package/payload/.agents/skills/revops/references/scoring-models.md +247 -0
  97. package/payload/.agents/skills/sales-enablement/SKILL.md +349 -0
  98. package/payload/.agents/skills/sales-enablement/evals/evals.json +91 -0
  99. package/payload/.agents/skills/sales-enablement/references/deck-frameworks.md +263 -0
  100. package/payload/.agents/skills/sales-enablement/references/demo-scripts.md +355 -0
  101. package/payload/.agents/skills/sales-enablement/references/objection-library.md +270 -0
  102. package/payload/.agents/skills/sales-enablement/references/one-pager-templates.md +208 -0
  103. package/payload/.agents/skills/schema-markup/SKILL.md +179 -0
  104. package/payload/.agents/skills/schema-markup/evals/evals.json +87 -0
  105. package/payload/.agents/skills/schema-markup/references/schema-examples.md +398 -0
  106. package/payload/.agents/skills/seo-audit/SKILL.md +412 -0
  107. package/payload/.agents/skills/seo-audit/evals/evals.json +136 -0
  108. package/payload/.agents/skills/seo-audit/references/ai-writing-detection.md +200 -0
  109. package/payload/.agents/skills/signup-flow-cro/SKILL.md +359 -0
  110. package/payload/.agents/skills/signup-flow-cro/evals/evals.json +88 -0
  111. package/payload/.agents/skills/site-architecture/SKILL.md +357 -0
  112. package/payload/.agents/skills/site-architecture/evals/evals.json +88 -0
  113. package/payload/.agents/skills/site-architecture/references/mermaid-templates.md +216 -0
  114. package/payload/.agents/skills/site-architecture/references/navigation-patterns.md +305 -0
  115. package/payload/.agents/skills/site-architecture/references/site-type-templates.md +293 -0
  116. package/payload/.agents/skills/social-content/SKILL.md +278 -0
  117. package/payload/.agents/skills/social-content/evals/evals.json +92 -0
  118. package/payload/.agents/skills/social-content/references/platforms.md +170 -0
  119. package/payload/.agents/skills/social-content/references/post-templates.md +177 -0
  120. package/payload/.agents/skills/social-content/references/reverse-engineering.md +195 -0
  121. package/payload/.maya/executor.md +79 -0
  122. package/payload/.maya/meta-api-agent.md +48 -0
  123. package/payload/.maya/modes/consult.md +63 -0
  124. package/payload/.maya/modes/task.md +97 -0
  125. package/payload/.maya/planner.md +69 -0
  126. package/payload/.maya/researcher.md +51 -0
  127. package/payload/.maya/templates/plan.md +77 -0
  128. package/payload/.maya/templates/state.md +87 -0
  129. package/payload/.maya/templates/task-packet.md +75 -0
  130. package/payload/MAYA-CATALOG.md +115 -0
  131. package/payload/MAYA-DEPENDENCIES.md +58 -0
  132. package/payload/MAYA.md +151 -0
  133. package/payload/campaigns/README.md +14 -0
  134. package/payload/commands/maya-consult.md +28 -0
  135. package/payload/commands/maya-task.md +38 -0
  136. package/payload/commands/product.md +55 -0
  137. package/payload/research/README.md +14 -0
  138. package/payload/templates/README.md +15 -0
  139. package/payload/templates/plan.md +77 -0
  140. package/payload/templates/state.md +87 -0
  141. package/payload/templates/task-packet.md +75 -0
  142. package/payload/tools/REGISTRY.md +368 -0
  143. package/payload/tools/clis/README.md +187 -0
  144. package/payload/tools/clis/activecampaign.js +435 -0
  145. package/payload/tools/clis/adobe-analytics.js +161 -0
  146. package/payload/tools/clis/ahrefs.js +192 -0
  147. package/payload/tools/clis/amplitude.js +182 -0
  148. package/payload/tools/clis/apollo.js +142 -0
  149. package/payload/tools/clis/beehiiv.js +245 -0
  150. package/payload/tools/clis/brevo.js +368 -0
  151. package/payload/tools/clis/buffer.js +260 -0
  152. package/payload/tools/clis/calendly.js +253 -0
  153. package/payload/tools/clis/clearbit.js +163 -0
  154. package/payload/tools/clis/customer-io.js +205 -0
  155. package/payload/tools/clis/dataforseo.js +257 -0
  156. package/payload/tools/clis/demio.js +149 -0
  157. package/payload/tools/clis/dub.js +158 -0
  158. package/payload/tools/clis/g2.js +186 -0
  159. package/payload/tools/clis/ga4.js +194 -0
  160. package/payload/tools/clis/google-ads.js +189 -0
  161. package/payload/tools/clis/google-search-console.js +166 -0
  162. package/payload/tools/clis/hotjar.js +167 -0
  163. package/payload/tools/clis/hunter.js +249 -0
  164. package/payload/tools/clis/instantly.js +270 -0
  165. package/payload/tools/clis/intercom.js +399 -0
  166. package/payload/tools/clis/keywords-everywhere.js +185 -0
  167. package/payload/tools/clis/kit.js +232 -0
  168. package/payload/tools/clis/klaviyo.js +348 -0
  169. package/payload/tools/clis/lemlist.js +221 -0
  170. package/payload/tools/clis/linkedin-ads.js +185 -0
  171. package/payload/tools/clis/livestorm.js +292 -0
  172. package/payload/tools/clis/mailchimp.js +220 -0
  173. package/payload/tools/clis/mention-me.js +161 -0
  174. package/payload/tools/clis/meta-ads.js +181 -0
  175. package/payload/tools/clis/mixpanel.js +248 -0
  176. package/payload/tools/clis/onesignal.js +241 -0
  177. package/payload/tools/clis/optimizely.js +233 -0
  178. package/payload/tools/clis/paddle.js +385 -0
  179. package/payload/tools/clis/partnerstack.js +382 -0
  180. package/payload/tools/clis/plausible.js +249 -0
  181. package/payload/tools/clis/postmark.js +375 -0
  182. package/payload/tools/clis/resend.js +370 -0
  183. package/payload/tools/clis/rewardful.js +160 -0
  184. package/payload/tools/clis/savvycal.js +223 -0
  185. package/payload/tools/clis/segment.js +192 -0
  186. package/payload/tools/clis/semrush.js +207 -0
  187. package/payload/tools/clis/sendgrid.js +211 -0
  188. package/payload/tools/clis/snov.js +237 -0
  189. package/payload/tools/clis/tiktok-ads.js +190 -0
  190. package/payload/tools/clis/tolt.js +153 -0
  191. package/payload/tools/clis/trustpilot.js +276 -0
  192. package/payload/tools/clis/typeform.js +269 -0
  193. package/payload/tools/clis/wistia.js +256 -0
  194. package/payload/tools/clis/zapier.js +160 -0
  195. package/payload/tools/integrations/activecampaign.md +337 -0
  196. package/payload/tools/integrations/adobe-analytics.md +156 -0
  197. package/payload/tools/integrations/ahrefs.md +142 -0
  198. package/payload/tools/integrations/amplitude.md +135 -0
  199. package/payload/tools/integrations/apollo.md +148 -0
  200. package/payload/tools/integrations/beehiiv.md +157 -0
  201. package/payload/tools/integrations/brevo.md +268 -0
  202. package/payload/tools/integrations/buffer.md +138 -0
  203. package/payload/tools/integrations/calendly.md +161 -0
  204. package/payload/tools/integrations/clearbit.md +142 -0
  205. package/payload/tools/integrations/customer-io.md +187 -0
  206. package/payload/tools/integrations/dataforseo.md +165 -0
  207. package/payload/tools/integrations/demio.md +182 -0
  208. package/payload/tools/integrations/dub-co.md +160 -0
  209. package/payload/tools/integrations/g2.md +179 -0
  210. package/payload/tools/integrations/ga4.md +126 -0
  211. package/payload/tools/integrations/google-ads.md +159 -0
  212. package/payload/tools/integrations/google-search-console.md +147 -0
  213. package/payload/tools/integrations/hotjar.md +147 -0
  214. package/payload/tools/integrations/hubspot.md +178 -0
  215. package/payload/tools/integrations/hunter.md +90 -0
  216. package/payload/tools/integrations/instantly.md +104 -0
  217. package/payload/tools/integrations/intercom.md +292 -0
  218. package/payload/tools/integrations/keywords-everywhere.md +207 -0
  219. package/payload/tools/integrations/kit.md +167 -0
  220. package/payload/tools/integrations/klaviyo.md +228 -0
  221. package/payload/tools/integrations/lemlist.md +110 -0
  222. package/payload/tools/integrations/linkedin-ads.md +164 -0
  223. package/payload/tools/integrations/livestorm.md +313 -0
  224. package/payload/tools/integrations/mailchimp.md +150 -0
  225. package/payload/tools/integrations/mention-me.md +160 -0
  226. package/payload/tools/integrations/meta-ads.md +147 -0
  227. package/payload/tools/integrations/mixpanel.md +137 -0
  228. package/payload/tools/integrations/onesignal.md +229 -0
  229. package/payload/tools/integrations/optimizely.md +171 -0
  230. package/payload/tools/integrations/paddle.md +212 -0
  231. package/payload/tools/integrations/partnerstack.md +222 -0
  232. package/payload/tools/integrations/plausible.md +177 -0
  233. package/payload/tools/integrations/posthog.md +151 -0
  234. package/payload/tools/integrations/postmark.md +234 -0
  235. package/payload/tools/integrations/resend.md +168 -0
  236. package/payload/tools/integrations/rewardful.md +147 -0
  237. package/payload/tools/integrations/salesforce.md +150 -0
  238. package/payload/tools/integrations/savvycal.md +181 -0
  239. package/payload/tools/integrations/segment.md +159 -0
  240. package/payload/tools/integrations/semrush.md +121 -0
  241. package/payload/tools/integrations/sendgrid.md +161 -0
  242. package/payload/tools/integrations/shopify.md +176 -0
  243. package/payload/tools/integrations/snov.md +94 -0
  244. package/payload/tools/integrations/stripe.md +148 -0
  245. package/payload/tools/integrations/tiktok-ads.md +161 -0
  246. package/payload/tools/integrations/tolt.md +144 -0
  247. package/payload/tools/integrations/trustpilot.md +191 -0
  248. package/payload/tools/integrations/typeform.md +190 -0
  249. package/payload/tools/integrations/webflow.md +198 -0
  250. package/payload/tools/integrations/wistia.md +164 -0
  251. package/payload/tools/integrations/wordpress.md +175 -0
  252. package/payload/tools/integrations/zapier.md +150 -0
  253. package/payload/tools/meta/README.md +55 -0
  254. package/payload/tools/meta/meta-cache-schema.md +65 -0
  255. package/payload/tools/meta/meta-fetch.ps1 +324 -0
  256. package/payload/tools/meta/meta-fetch.test.ps1 +38 -0
  257. package/vendor/shared-installer/manifests/claude-files.json +13 -0
  258. package/vendor/shared-installer/manifests/codex-files.json +13 -0
  259. package/vendor/shared-installer/manifests/common-files.json +13 -0
  260. package/vendor/shared-installer/package.json +15 -0
  261. package/vendor/shared-installer/src/bootstrap.js +12 -0
  262. package/vendor/shared-installer/src/cli-options.js +53 -0
  263. package/vendor/shared-installer/src/fs.js +105 -0
  264. package/vendor/shared-installer/src/index.js +44 -0
  265. package/vendor/shared-installer/src/install.js +157 -0
  266. package/vendor/shared-installer/src/manifest.js +52 -0
  267. package/vendor/shared-installer/templates/claude/.claude/skills/.gitkeep +1 -0
  268. package/vendor/shared-installer/templates/claude/CLAUDE.md +27 -0
  269. package/vendor/shared-installer/templates/codex/.agent/skills/.gitkeep +1 -0
  270. package/vendor/shared-installer/templates/codex/AGENTS.md +27 -0
@@ -0,0 +1,205 @@
1
+ #!/usr/bin/env node
2
+
3
+ const APP_KEY = process.env.CUSTOMERIO_APP_KEY
4
+ const SITE_ID = process.env.CUSTOMERIO_SITE_ID
5
+ const API_KEY = process.env.CUSTOMERIO_API_KEY
6
+
7
+ const TRACK_URL = 'https://track.customer.io/api/v1'
8
+ const APP_URL = 'https://api.customer.io/v1'
9
+
10
+ const hasTrackAuth = SITE_ID && API_KEY
11
+ const hasAppAuth = APP_KEY
12
+
13
+ if (!hasTrackAuth && !hasAppAuth) {
14
+ console.error(JSON.stringify({ error: 'CUSTOMERIO_APP_KEY (for App API) or CUSTOMERIO_SITE_ID + CUSTOMERIO_API_KEY (for Track API) environment variables required' }))
15
+ process.exit(1)
16
+ }
17
+
18
+ const basicAuth = hasTrackAuth ? Buffer.from(`${SITE_ID}:${API_KEY}`).toString('base64') : null
19
+
20
+ async function trackApi(method, path, body) {
21
+ if (!hasTrackAuth) {
22
+ return { error: 'Track API requires CUSTOMERIO_SITE_ID and CUSTOMERIO_API_KEY environment variables' }
23
+ }
24
+ if (args['dry-run']) {
25
+ return { _dry_run: true, method, url: `${TRACK_URL}${path}`, headers: { Authorization: '***', 'Content-Type': 'application/json' }, body: body || undefined }
26
+ }
27
+ const res = await fetch(`${TRACK_URL}${path}`, {
28
+ method,
29
+ headers: {
30
+ 'Authorization': `Basic ${basicAuth}`,
31
+ 'Content-Type': 'application/json',
32
+ },
33
+ body: body ? JSON.stringify(body) : undefined,
34
+ })
35
+ const text = await res.text()
36
+ try {
37
+ return JSON.parse(text)
38
+ } catch {
39
+ return { status: res.status, body: text }
40
+ }
41
+ }
42
+
43
+ async function appApi(method, path, body) {
44
+ if (!hasAppAuth) {
45
+ return { error: 'App API requires CUSTOMERIO_APP_KEY environment variable' }
46
+ }
47
+ if (args['dry-run']) {
48
+ return { _dry_run: true, method, url: `${APP_URL}${path}`, headers: { Authorization: '***', 'Content-Type': 'application/json' }, body: body || undefined }
49
+ }
50
+ const res = await fetch(`${APP_URL}${path}`, {
51
+ method,
52
+ headers: {
53
+ 'Authorization': `Bearer ${APP_KEY}`,
54
+ 'Content-Type': 'application/json',
55
+ },
56
+ body: body ? JSON.stringify(body) : undefined,
57
+ })
58
+ const text = await res.text()
59
+ try {
60
+ return JSON.parse(text)
61
+ } catch {
62
+ return { status: res.status, body: text }
63
+ }
64
+ }
65
+
66
+ function parseArgs(args) {
67
+ const result = { _: [] }
68
+ for (let i = 0; i < args.length; i++) {
69
+ const arg = args[i]
70
+ if (arg.startsWith('--')) {
71
+ const key = arg.slice(2)
72
+ const next = args[i + 1]
73
+ if (next && !next.startsWith('--')) {
74
+ result[key] = next
75
+ i++
76
+ } else {
77
+ result[key] = true
78
+ }
79
+ } else {
80
+ result._.push(arg)
81
+ }
82
+ }
83
+ return result
84
+ }
85
+
86
+ const args = parseArgs(process.argv.slice(2))
87
+ const [cmd, sub, ...rest] = args._
88
+
89
+ async function main() {
90
+ let result
91
+
92
+ switch (cmd) {
93
+ case 'customers':
94
+ switch (sub) {
95
+ case 'identify': {
96
+ const customerId = rest[0] || args.id
97
+ if (!customerId) { result = { error: 'Customer ID required (positional arg or --id)' }; break }
98
+ const body = {}
99
+ if (args.email) body.email = args.email
100
+ if (args['first-name']) body.first_name = args['first-name']
101
+ if (args['last-name']) body.last_name = args['last-name']
102
+ if (args['created-at']) body.created_at = parseInt(args['created-at'])
103
+ if (args.plan) body.plan = args.plan
104
+ if (args.data) Object.assign(body, JSON.parse(args.data))
105
+ result = await trackApi('PUT', `/customers/${customerId}`, body)
106
+ break
107
+ }
108
+ case 'get': {
109
+ const customerId = rest[0] || args.id
110
+ if (!customerId) { result = { error: 'Customer ID required (positional arg or --id)' }; break }
111
+ result = await appApi('GET', `/customers/${customerId}/attributes`)
112
+ break
113
+ }
114
+ case 'delete': {
115
+ const customerId = rest[0] || args.id
116
+ if (!customerId) { result = { error: 'Customer ID required (positional arg or --id)' }; break }
117
+ result = await trackApi('DELETE', `/customers/${customerId}`)
118
+ break
119
+ }
120
+ case 'track-event': {
121
+ const customerId = rest[0] || args.id
122
+ if (!customerId) { result = { error: 'Customer ID required (positional arg or --id)' }; break }
123
+ if (!args.name) { result = { error: '--name required (event name)' }; break }
124
+ const body = { name: args.name }
125
+ if (args.data) body.data = JSON.parse(args.data)
126
+ result = await trackApi('POST', `/customers/${customerId}/events`, body)
127
+ break
128
+ }
129
+ default:
130
+ result = { error: 'Unknown customers subcommand. Use: identify, get, delete, track-event' }
131
+ }
132
+ break
133
+
134
+ case 'campaigns':
135
+ switch (sub) {
136
+ case 'list':
137
+ result = await appApi('GET', '/campaigns')
138
+ break
139
+ case 'get': {
140
+ const campaignId = rest[0] || args.id
141
+ if (!campaignId) { result = { error: 'Campaign ID required (positional arg or --id)' }; break }
142
+ result = await appApi('GET', `/campaigns/${campaignId}`)
143
+ break
144
+ }
145
+ case 'metrics': {
146
+ const campaignId = rest[0] || args.id
147
+ if (!campaignId) { result = { error: 'Campaign ID required (positional arg or --id)' }; break }
148
+ result = await appApi('GET', `/campaigns/${campaignId}/metrics`)
149
+ break
150
+ }
151
+ case 'trigger': {
152
+ const campaignId = rest[0] || args.id
153
+ if (!campaignId) { result = { error: 'Campaign ID required (positional arg or --id)' }; break }
154
+ const body = {}
155
+ if (args.emails) body.emails = args.emails.split(',')
156
+ if (args.ids) body.ids = args.ids.split(',')
157
+ if (args.data) body.data = JSON.parse(args.data)
158
+ result = await appApi('POST', `/campaigns/${campaignId}/triggers`, body)
159
+ break
160
+ }
161
+ default:
162
+ result = { error: 'Unknown campaigns subcommand. Use: list, get, metrics, trigger' }
163
+ }
164
+ break
165
+
166
+ case 'send':
167
+ switch (sub) {
168
+ case 'email': {
169
+ const body = {
170
+ transactional_message_id: args['message-id'],
171
+ to: args.to,
172
+ identifiers: {},
173
+ }
174
+ if (args['identifier-id']) body.identifiers.id = args['identifier-id']
175
+ if (args['identifier-email']) body.identifiers.email = args['identifier-email']
176
+ if (args.data) body.message_data = JSON.parse(args.data)
177
+ if (args.from) body.from = args.from
178
+ if (args.subject) body.subject = args.subject
179
+ if (args.body) body.body = args.body
180
+ result = await appApi('POST', '/send/email', body)
181
+ break
182
+ }
183
+ default:
184
+ result = { error: 'Unknown send subcommand. Use: email' }
185
+ }
186
+ break
187
+
188
+ default:
189
+ result = {
190
+ error: 'Unknown command',
191
+ usage: {
192
+ customers: 'customers [identify|get|delete|track-event] <customer_id> [--email <email>] [--first-name <name>] [--plan <plan>] [--data <json>] [--name <event>]',
193
+ campaigns: 'campaigns [list|get|metrics|trigger] [campaign_id] [--emails <e1,e2>] [--ids <id1,id2>] [--data <json>]',
194
+ send: 'send email --message-id <id> --to <email> [--identifier-id <id>] [--identifier-email <email>] [--data <json>]',
195
+ }
196
+ }
197
+ }
198
+
199
+ console.log(JSON.stringify(result, null, 2))
200
+ }
201
+
202
+ main().catch(err => {
203
+ console.error(JSON.stringify({ error: err.message }))
204
+ process.exit(1)
205
+ })
@@ -0,0 +1,257 @@
1
+ #!/usr/bin/env node
2
+
3
+ const LOGIN = process.env.DATAFORSEO_LOGIN
4
+ const PASSWORD = process.env.DATAFORSEO_PASSWORD
5
+ const BASE_URL = 'https://api.dataforseo.com/v3'
6
+
7
+ if (!LOGIN || !PASSWORD) {
8
+ console.error(JSON.stringify({ error: 'DATAFORSEO_LOGIN and DATAFORSEO_PASSWORD environment variables required' }))
9
+ process.exit(1)
10
+ }
11
+
12
+ const AUTH = 'Basic ' + Buffer.from(`${LOGIN}:${PASSWORD}`).toString('base64')
13
+
14
+ async function api(method, path, body) {
15
+ if (args['dry-run']) {
16
+ return { _dry_run: true, method, url: `${BASE_URL}${path}`, headers: { Authorization: '***', 'Content-Type': 'application/json' }, body: body || undefined }
17
+ }
18
+ const res = await fetch(`${BASE_URL}${path}`, {
19
+ method,
20
+ headers: {
21
+ 'Authorization': AUTH,
22
+ 'Content-Type': 'application/json',
23
+ },
24
+ body: body ? JSON.stringify(body) : undefined,
25
+ })
26
+ const text = await res.text()
27
+ try {
28
+ return JSON.parse(text)
29
+ } catch {
30
+ return { status: res.status, body: text }
31
+ }
32
+ }
33
+
34
+ function parseArgs(args) {
35
+ const result = { _: [] }
36
+ for (let i = 0; i < args.length; i++) {
37
+ const arg = args[i]
38
+ if (arg.startsWith('--')) {
39
+ const key = arg.slice(2)
40
+ const next = args[i + 1]
41
+ if (next && !next.startsWith('--')) {
42
+ result[key] = next
43
+ i++
44
+ } else {
45
+ result[key] = true
46
+ }
47
+ } else {
48
+ result._.push(arg)
49
+ }
50
+ }
51
+ return result
52
+ }
53
+
54
+ const args = parseArgs(process.argv.slice(2))
55
+ const [cmd, sub, ...rest] = args._
56
+
57
+ async function main() {
58
+ let result
59
+ const location = args.location || 'United States'
60
+ const locationCode = args['location-code'] ? Number(args['location-code']) : 2840
61
+ const language = args.language || 'English'
62
+ const languageCode = args['language-code'] || 'en'
63
+ const limit = args.limit ? Number(args.limit) : 100
64
+
65
+ switch (cmd) {
66
+ case 'serp':
67
+ switch (sub) {
68
+ case 'google': {
69
+ const keyword = args.keyword
70
+ if (!keyword) { result = { error: '--keyword required' }; break }
71
+ result = await api('POST', '/serp/google/organic/live/regular', [{
72
+ keyword,
73
+ location_name: location,
74
+ language_name: language,
75
+ }])
76
+ break
77
+ }
78
+ case 'locations':
79
+ result = await api('GET', '/serp/google/locations')
80
+ break
81
+ case 'languages':
82
+ result = await api('GET', '/serp/google/languages')
83
+ break
84
+ default:
85
+ result = { error: 'Unknown serp subcommand. Use: google, locations, languages' }
86
+ }
87
+ break
88
+
89
+ case 'keywords':
90
+ switch (sub) {
91
+ case 'volume': {
92
+ const keywords = args.keywords?.split(',')
93
+ if (!keywords) { result = { error: '--keywords required (comma-separated)' }; break }
94
+ result = await api('POST', '/keywords_data/google_ads/search_volume/live', [{
95
+ keywords,
96
+ location_code: locationCode,
97
+ language_code: languageCode,
98
+ }])
99
+ break
100
+ }
101
+ case 'for-site': {
102
+ const target = args.target
103
+ if (!target) { result = { error: '--target required (domain)' }; break }
104
+ result = await api('POST', '/keywords_data/google_ads/keywords_for_site/live', [{
105
+ target,
106
+ location_code: locationCode,
107
+ language_code: languageCode,
108
+ }])
109
+ break
110
+ }
111
+ case 'for-keywords': {
112
+ const keywords = args.keywords?.split(',')
113
+ if (!keywords) { result = { error: '--keywords required (comma-separated)' }; break }
114
+ result = await api('POST', '/keywords_data/google_ads/keywords_for_keywords/live', [{
115
+ keywords,
116
+ location_code: locationCode,
117
+ language_code: languageCode,
118
+ }])
119
+ break
120
+ }
121
+ case 'trends': {
122
+ const keywords = args.keywords?.split(',')
123
+ if (!keywords) { result = { error: '--keywords required (comma-separated)' }; break }
124
+ result = await api('POST', '/keywords_data/google_trends/explore/live', [{
125
+ keywords,
126
+ location_code: locationCode,
127
+ language_code: languageCode,
128
+ }])
129
+ break
130
+ }
131
+ default:
132
+ result = { error: 'Unknown keywords subcommand. Use: volume, for-site, for-keywords, trends' }
133
+ }
134
+ break
135
+
136
+ case 'backlinks':
137
+ switch (sub) {
138
+ case 'summary': {
139
+ const target = args.target
140
+ if (!target) { result = { error: '--target required' }; break }
141
+ result = await api('POST', '/backlinks/summary/live', [{
142
+ target,
143
+ backlinks_status_type: 'live',
144
+ }])
145
+ break
146
+ }
147
+ case 'list': {
148
+ const target = args.target
149
+ if (!target) { result = { error: '--target required' }; break }
150
+ result = await api('POST', '/backlinks/backlinks/live', [{
151
+ target,
152
+ mode: args.mode || 'as_is',
153
+ limit,
154
+ backlinks_status_type: 'live',
155
+ }])
156
+ break
157
+ }
158
+ case 'refdomains': {
159
+ const target = args.target
160
+ if (!target) { result = { error: '--target required' }; break }
161
+ result = await api('POST', '/backlinks/referring_domains/live', [{
162
+ target,
163
+ limit,
164
+ }])
165
+ break
166
+ }
167
+ case 'anchors': {
168
+ const target = args.target
169
+ if (!target) { result = { error: '--target required' }; break }
170
+ result = await api('POST', '/backlinks/anchors/live', [{
171
+ target,
172
+ limit,
173
+ }])
174
+ break
175
+ }
176
+ case 'index':
177
+ result = await api('GET', '/backlinks/index')
178
+ break
179
+ default:
180
+ result = { error: 'Unknown backlinks subcommand. Use: summary, list, refdomains, anchors, index' }
181
+ }
182
+ break
183
+
184
+ case 'onpage':
185
+ switch (sub) {
186
+ case 'audit': {
187
+ const url = args.url
188
+ if (!url) { result = { error: '--url required' }; break }
189
+ result = await api('POST', '/on_page/instant_pages', [{
190
+ url,
191
+ enable_javascript: args['no-js'] ? false : true,
192
+ }])
193
+ break
194
+ }
195
+ default:
196
+ result = { error: 'Unknown onpage subcommand. Use: audit' }
197
+ }
198
+ break
199
+
200
+ case 'labs':
201
+ switch (sub) {
202
+ case 'competitors': {
203
+ const target = args.target
204
+ if (!target) { result = { error: '--target required' }; break }
205
+ result = await api('POST', '/dataforseo_labs/google/competitors_domain/live', [{
206
+ target,
207
+ location_code: locationCode,
208
+ language_code: languageCode,
209
+ limit,
210
+ }])
211
+ break
212
+ }
213
+ case 'ranked-keywords': {
214
+ const target = args.target
215
+ if (!target) { result = { error: '--target required' }; break }
216
+ result = await api('POST', '/dataforseo_labs/google/ranked_keywords/live', [{
217
+ target,
218
+ location_code: locationCode,
219
+ language_code: languageCode,
220
+ limit,
221
+ }])
222
+ break
223
+ }
224
+ case 'domain-intersection': {
225
+ const targets = args.targets?.split(',')
226
+ if (!targets || targets.length < 2) { result = { error: '--targets required (comma-separated, at least 2 domains)' }; break }
227
+ const payload = { location_code: locationCode, language_code: languageCode, limit }
228
+ targets.forEach((t, i) => { payload[`target${i + 1}`] = t })
229
+ result = await api('POST', '/dataforseo_labs/google/domain_intersection/live', [payload])
230
+ break
231
+ }
232
+ default:
233
+ result = { error: 'Unknown labs subcommand. Use: competitors, ranked-keywords, domain-intersection' }
234
+ }
235
+ break
236
+
237
+ default:
238
+ result = {
239
+ error: 'Unknown command',
240
+ usage: {
241
+ serp: 'serp [google --keyword <kw> | locations | languages]',
242
+ keywords: 'keywords [volume --keywords <kw1,kw2> | for-site --target <domain> | for-keywords --keywords <kw1,kw2> | trends --keywords <kw1,kw2>]',
243
+ backlinks: 'backlinks [summary --target <domain> | list --target <domain> | refdomains --target <domain> | anchors --target <domain> | index]',
244
+ onpage: 'onpage [audit --url <url>]',
245
+ labs: 'labs [competitors --target <domain> | ranked-keywords --target <domain> | domain-intersection --targets <d1,d2>]',
246
+ options: '--location-code <code> --language-code <code> --limit <n>',
247
+ }
248
+ }
249
+ }
250
+
251
+ console.log(JSON.stringify(result, null, 2))
252
+ }
253
+
254
+ main().catch(err => {
255
+ console.error(JSON.stringify({ error: err.message }))
256
+ process.exit(1)
257
+ })
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env node
2
+
3
+ const API_KEY = process.env.DEMIO_API_KEY
4
+ const API_SECRET = process.env.DEMIO_API_SECRET
5
+ const BASE_URL = 'https://my.demio.com/api/v1'
6
+
7
+ if (!API_KEY) {
8
+ console.error(JSON.stringify({ error: 'DEMIO_API_KEY environment variable required' }))
9
+ process.exit(1)
10
+ }
11
+
12
+ if (!API_SECRET) {
13
+ console.error(JSON.stringify({ error: 'DEMIO_API_SECRET environment variable required' }))
14
+ process.exit(1)
15
+ }
16
+
17
+ async function api(method, path, body) {
18
+ if (args['dry-run']) {
19
+ return { _dry_run: true, method, url: `${BASE_URL}${path}`, headers: { 'Api-Key': '***', 'Api-Secret': '***', 'Content-Type': 'application/json', Accept: 'application/json' }, body: body || undefined }
20
+ }
21
+ const res = await fetch(`${BASE_URL}${path}`, {
22
+ method,
23
+ headers: {
24
+ 'Api-Key': API_KEY,
25
+ 'Api-Secret': API_SECRET,
26
+ 'Content-Type': 'application/json',
27
+ 'Accept': 'application/json',
28
+ },
29
+ body: body ? JSON.stringify(body) : undefined,
30
+ })
31
+ const text = await res.text()
32
+ try {
33
+ return JSON.parse(text)
34
+ } catch {
35
+ return { status: res.status, body: text }
36
+ }
37
+ }
38
+
39
+ function parseArgs(args) {
40
+ const result = { _: [] }
41
+ for (let i = 0; i < args.length; i++) {
42
+ const arg = args[i]
43
+ if (arg.startsWith('--')) {
44
+ const key = arg.slice(2)
45
+ const next = args[i + 1]
46
+ if (next && !next.startsWith('--')) {
47
+ result[key] = next
48
+ i++
49
+ } else {
50
+ result[key] = true
51
+ }
52
+ } else {
53
+ result._.push(arg)
54
+ }
55
+ }
56
+ return result
57
+ }
58
+
59
+ const args = parseArgs(process.argv.slice(2))
60
+ const [cmd, sub, ...rest] = args._
61
+
62
+ async function main() {
63
+ let result
64
+
65
+ switch (cmd) {
66
+ case 'ping':
67
+ result = await api('GET', '/ping')
68
+ break
69
+
70
+ case 'events':
71
+ switch (sub) {
72
+ case 'list': {
73
+ const type = args.type
74
+ let qs = ''
75
+ if (type) qs = `?type=${encodeURIComponent(type)}`
76
+ result = await api('GET', `/events${qs}`)
77
+ break
78
+ }
79
+ case 'get': {
80
+ const id = args.id
81
+ if (!id) { result = { error: '--id required' }; break }
82
+ result = await api('GET', `/event/${id}`)
83
+ break
84
+ }
85
+ case 'date': {
86
+ const eventId = args['event-id']
87
+ const dateId = args['date-id']
88
+ if (!eventId) { result = { error: '--event-id required' }; break }
89
+ if (!dateId) { result = { error: '--date-id required' }; break }
90
+ result = await api('GET', `/event/${eventId}/date/${dateId}`)
91
+ break
92
+ }
93
+ default:
94
+ result = { error: 'Unknown events subcommand. Use: list, get, date' }
95
+ }
96
+ break
97
+
98
+ case 'register':
99
+ switch (sub) {
100
+ case 'create': {
101
+ const id = args.id || args['event-id']
102
+ const name = args.name
103
+ const email = args.email
104
+ if (!id) { result = { error: '--id (event id) required' }; break }
105
+ if (!name) { result = { error: '--name required' }; break }
106
+ if (!email) { result = { error: '--email required' }; break }
107
+ const payload = { id, name, email }
108
+ if (args['date-id']) payload.date_id = args['date-id']
109
+ if (args['ref-url']) payload.ref_url = args['ref-url']
110
+ result = await api('POST', '/event/register', payload)
111
+ break
112
+ }
113
+ default:
114
+ result = { error: 'Unknown register subcommand. Use: create' }
115
+ }
116
+ break
117
+
118
+ case 'participants':
119
+ switch (sub) {
120
+ case 'list': {
121
+ const dateId = args['date-id']
122
+ if (!dateId) { result = { error: '--date-id required' }; break }
123
+ result = await api('GET', `/date/${dateId}/participants`)
124
+ break
125
+ }
126
+ default:
127
+ result = { error: 'Unknown participants subcommand. Use: list' }
128
+ }
129
+ break
130
+
131
+ default:
132
+ result = {
133
+ error: 'Unknown command',
134
+ usage: {
135
+ ping: 'ping',
136
+ events: 'events [list --type <upcoming|past|all> | get --id <id> | date --event-id <id> --date-id <id>]',
137
+ register: 'register [create --id <event_id> --name <name> --email <email> --date-id <date_id>]',
138
+ participants: 'participants [list --date-id <id>]',
139
+ }
140
+ }
141
+ }
142
+
143
+ console.log(JSON.stringify(result, null, 2))
144
+ }
145
+
146
+ main().catch(err => {
147
+ console.error(JSON.stringify({ error: err.message }))
148
+ process.exit(1)
149
+ })