diff --git a/apps/sim/blocks/blocks/ahrefs.ts b/apps/sim/blocks/blocks/ahrefs.ts index 80e56aa7d6b..cd5b5e22347 100644 --- a/apps/sim/blocks/blocks/ahrefs.ts +++ b/apps/sim/blocks/blocks/ahrefs.ts @@ -3,6 +3,45 @@ import type { BlockConfig, BlockMeta } from '@/blocks/types' import { AuthMode, IntegrationType } from '@/blocks/types' import type { AhrefsResponse } from '@/tools/ahrefs/types' +const COUNTRY_OPTIONS = [ + { label: 'United States', id: 'us' }, + { label: 'United Kingdom', id: 'gb' }, + { label: 'Germany', id: 'de' }, + { label: 'France', id: 'fr' }, + { label: 'Spain', id: 'es' }, + { label: 'Italy', id: 'it' }, + { label: 'Canada', id: 'ca' }, + { label: 'Australia', id: 'au' }, + { label: 'Japan', id: 'jp' }, + { label: 'Brazil', id: 'br' }, + { label: 'India', id: 'in' }, + { label: 'Netherlands', id: 'nl' }, + { label: 'Poland', id: 'pl' }, + { label: 'Russia', id: 'ru' }, + { label: 'Mexico', id: 'mx' }, +] + +const MODE_OPTIONS = [ + { label: 'Domain (entire domain)', id: 'domain' }, + { label: 'Prefix (URL prefix)', id: 'prefix' }, + { label: 'Subdomains (include all)', id: 'subdomains' }, + { label: 'Exact (exact URL)', id: 'exact' }, +] + +const DATE_WAND_CONFIG = { + enabled: true, + prompt: `Generate a date in YYYY-MM-DD format based on the user's description. +Examples: +- "today" -> Current date in YYYY-MM-DD format +- "yesterday" -> Yesterday's date in YYYY-MM-DD format +- "last week" -> Date 7 days ago in YYYY-MM-DD format +- "beginning of this month" -> First day of current month in YYYY-MM-DD format + +Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, no extra text.`, + placeholder: 'Describe the date (e.g., "yesterday", "last week", "start of month")...', + generationType: 'timestamp' as const, +} + export const AhrefsBlock: BlockConfig = { type: 'ahrefs', name: 'Ahrefs', @@ -10,7 +49,7 @@ export const AhrefsBlock: BlockConfig = { authMode: AuthMode.ApiKey, longDescription: 'Integrate Ahrefs SEO tools into your workflow. Analyze domain ratings, backlinks, organic keywords, top pages, and more. Requires an Ahrefs Enterprise plan with API access.', - docsLink: 'https://docs.ahrefs.com/docs/api/reference/introduction', + docsLink: 'https://docs.sim.ai/integrations/ahrefs', category: 'tools', integrationType: IntegrationType.Analytics, bgColor: '#FFFFFF', @@ -22,13 +61,15 @@ export const AhrefsBlock: BlockConfig = { type: 'dropdown', options: [ { label: 'Domain Rating', id: 'ahrefs_domain_rating' }, + { label: 'Metrics Overview', id: 'ahrefs_metrics' }, { label: 'Backlinks', id: 'ahrefs_backlinks' }, { label: 'Backlinks Stats', id: 'ahrefs_backlinks_stats' }, { label: 'Referring Domains', id: 'ahrefs_referring_domains' }, + { label: 'Broken Backlinks', id: 'ahrefs_broken_backlinks' }, { label: 'Organic Keywords', id: 'ahrefs_organic_keywords' }, + { label: 'Organic Competitors', id: 'ahrefs_organic_competitors' }, { label: 'Top Pages', id: 'ahrefs_top_pages' }, { label: 'Keyword Overview', id: 'ahrefs_keyword_overview' }, - { label: 'Broken Backlinks', id: 'ahrefs_broken_backlinks' }, ], value: () => 'ahrefs_domain_rating', }, @@ -48,79 +89,81 @@ export const AhrefsBlock: BlockConfig = { placeholder: 'YYYY-MM-DD (defaults to today)', condition: { field: 'operation', value: 'ahrefs_domain_rating' }, mode: 'advanced', - wandConfig: { - enabled: true, - prompt: `Generate a date in YYYY-MM-DD format based on the user's description. -Examples: -- "today" -> Current date in YYYY-MM-DD format -- "yesterday" -> Yesterday's date in YYYY-MM-DD format -- "last week" -> Date 7 days ago in YYYY-MM-DD format -- "beginning of this month" -> First day of current month in YYYY-MM-DD format - -Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, no extra text.`, - placeholder: 'Describe the date (e.g., "yesterday", "last week", "start of month")...', - generationType: 'timestamp', - }, + wandConfig: DATE_WAND_CONFIG, }, - // Backlinks operation inputs + // Metrics operation inputs { id: 'target', title: 'Target Domain/URL', type: 'short-input', - placeholder: 'example.com or https://example.com/page', - condition: { field: 'operation', value: 'ahrefs_backlinks' }, + placeholder: 'example.com', + condition: { field: 'operation', value: 'ahrefs_metrics' }, required: true, }, + { + id: 'country', + title: 'Country', + type: 'dropdown', + options: COUNTRY_OPTIONS, + value: () => 'us', + condition: { field: 'operation', value: 'ahrefs_metrics' }, + mode: 'advanced', + }, { id: 'mode', title: 'Analysis Mode', type: 'dropdown', - options: [ - { label: 'Domain (entire domain)', id: 'domain' }, - { label: 'Prefix (URL prefix)', id: 'prefix' }, - { label: 'Subdomains (include all)', id: 'subdomains' }, - { label: 'Exact (exact URL)', id: 'exact' }, - ], + options: MODE_OPTIONS, value: () => 'domain', - condition: { field: 'operation', value: 'ahrefs_backlinks' }, + condition: { field: 'operation', value: 'ahrefs_metrics' }, mode: 'advanced', }, { - id: 'limit', - title: 'Limit', + id: 'date', + title: 'Date', type: 'short-input', - placeholder: '100', - condition: { field: 'operation', value: 'ahrefs_backlinks' }, + placeholder: 'YYYY-MM-DD (defaults to today)', + condition: { field: 'operation', value: 'ahrefs_metrics' }, mode: 'advanced', + wandConfig: DATE_WAND_CONFIG, }, + // Backlinks operation inputs { - id: 'offset', - title: 'Offset', + id: 'target', + title: 'Target Domain/URL', type: 'short-input', - placeholder: '0', + placeholder: 'example.com or https://example.com/page', + condition: { field: 'operation', value: 'ahrefs_backlinks' }, + required: true, + }, + { + id: 'mode', + title: 'Analysis Mode', + type: 'dropdown', + options: MODE_OPTIONS, + value: () => 'domain', condition: { field: 'operation', value: 'ahrefs_backlinks' }, mode: 'advanced', }, { - id: 'date', - title: 'Date', + id: 'history', + title: 'History', + type: 'dropdown', + options: [ + { label: 'All time (includes lost backlinks)', id: 'all_time' }, + { label: 'Live only', id: 'live' }, + ], + value: () => 'all_time', + condition: { field: 'operation', value: 'ahrefs_backlinks' }, + mode: 'advanced', + }, + { + id: 'limit', + title: 'Limit', type: 'short-input', - placeholder: 'YYYY-MM-DD (defaults to today)', + placeholder: '1000', condition: { field: 'operation', value: 'ahrefs_backlinks' }, mode: 'advanced', - wandConfig: { - enabled: true, - prompt: `Generate a date in YYYY-MM-DD format based on the user's description. -Examples: -- "today" -> Current date in YYYY-MM-DD format -- "yesterday" -> Yesterday's date in YYYY-MM-DD format -- "last week" -> Date 7 days ago in YYYY-MM-DD format -- "beginning of this month" -> First day of current month in YYYY-MM-DD format - -Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, no extra text.`, - placeholder: 'Describe the date (e.g., "yesterday", "last week", "start of month")...', - generationType: 'timestamp', - }, }, // Backlinks Stats operation inputs { @@ -135,12 +178,7 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n id: 'mode', title: 'Analysis Mode', type: 'dropdown', - options: [ - { label: 'Domain (entire domain)', id: 'domain' }, - { label: 'Prefix (URL prefix)', id: 'prefix' }, - { label: 'Subdomains (include all)', id: 'subdomains' }, - { label: 'Exact (exact URL)', id: 'exact' }, - ], + options: MODE_OPTIONS, value: () => 'domain', condition: { field: 'operation', value: 'ahrefs_backlinks_stats' }, mode: 'advanced', @@ -152,19 +190,7 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n placeholder: 'YYYY-MM-DD (defaults to today)', condition: { field: 'operation', value: 'ahrefs_backlinks_stats' }, mode: 'advanced', - wandConfig: { - enabled: true, - prompt: `Generate a date in YYYY-MM-DD format based on the user's description. -Examples: -- "today" -> Current date in YYYY-MM-DD format -- "yesterday" -> Yesterday's date in YYYY-MM-DD format -- "last week" -> Date 7 days ago in YYYY-MM-DD format -- "beginning of this month" -> First day of current month in YYYY-MM-DD format - -Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, no extra text.`, - placeholder: 'Describe the date (e.g., "yesterday", "last week", "start of month")...', - generationType: 'timestamp', - }, + wandConfig: DATE_WAND_CONFIG, }, // Referring Domains operation inputs { @@ -179,13 +205,20 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n id: 'mode', title: 'Analysis Mode', type: 'dropdown', + options: MODE_OPTIONS, + value: () => 'domain', + condition: { field: 'operation', value: 'ahrefs_referring_domains' }, + mode: 'advanced', + }, + { + id: 'history', + title: 'History', + type: 'dropdown', options: [ - { label: 'Domain (entire domain)', id: 'domain' }, - { label: 'Prefix (URL prefix)', id: 'prefix' }, - { label: 'Subdomains (include all)', id: 'subdomains' }, - { label: 'Exact (exact URL)', id: 'exact' }, + { label: 'All time (includes lost domains)', id: 'all_time' }, + { label: 'Live only', id: 'live' }, ], - value: () => 'domain', + value: () => 'all_time', condition: { field: 'operation', value: 'ahrefs_referring_domains' }, mode: 'advanced', }, @@ -193,38 +226,35 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n id: 'limit', title: 'Limit', type: 'short-input', - placeholder: '100', + placeholder: '1000', condition: { field: 'operation', value: 'ahrefs_referring_domains' }, mode: 'advanced', }, + // Broken Backlinks operation inputs { - id: 'offset', - title: 'Offset', + id: 'target', + title: 'Target Domain/URL', type: 'short-input', - placeholder: '0', - condition: { field: 'operation', value: 'ahrefs_referring_domains' }, + placeholder: 'example.com', + condition: { field: 'operation', value: 'ahrefs_broken_backlinks' }, + required: true, + }, + { + id: 'mode', + title: 'Analysis Mode', + type: 'dropdown', + options: MODE_OPTIONS, + value: () => 'domain', + condition: { field: 'operation', value: 'ahrefs_broken_backlinks' }, mode: 'advanced', }, { - id: 'date', - title: 'Date', + id: 'limit', + title: 'Limit', type: 'short-input', - placeholder: 'YYYY-MM-DD (defaults to today)', - condition: { field: 'operation', value: 'ahrefs_referring_domains' }, + placeholder: '1000', + condition: { field: 'operation', value: 'ahrefs_broken_backlinks' }, mode: 'advanced', - wandConfig: { - enabled: true, - prompt: `Generate a date in YYYY-MM-DD format based on the user's description. -Examples: -- "today" -> Current date in YYYY-MM-DD format -- "yesterday" -> Yesterday's date in YYYY-MM-DD format -- "last week" -> Date 7 days ago in YYYY-MM-DD format -- "beginning of this month" -> First day of current month in YYYY-MM-DD format - -Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, no extra text.`, - placeholder: 'Describe the date (e.g., "yesterday", "last week", "start of month")...', - generationType: 'timestamp', - }, }, // Organic Keywords operation inputs { @@ -239,23 +269,7 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n id: 'country', title: 'Country', type: 'dropdown', - options: [ - { label: 'United States', id: 'us' }, - { label: 'United Kingdom', id: 'gb' }, - { label: 'Germany', id: 'de' }, - { label: 'France', id: 'fr' }, - { label: 'Spain', id: 'es' }, - { label: 'Italy', id: 'it' }, - { label: 'Canada', id: 'ca' }, - { label: 'Australia', id: 'au' }, - { label: 'Japan', id: 'jp' }, - { label: 'Brazil', id: 'br' }, - { label: 'India', id: 'in' }, - { label: 'Netherlands', id: 'nl' }, - { label: 'Poland', id: 'pl' }, - { label: 'Russia', id: 'ru' }, - { label: 'Mexico', id: 'mx' }, - ], + options: COUNTRY_OPTIONS, value: () => 'us', condition: { field: 'operation', value: 'ahrefs_organic_keywords' }, mode: 'advanced', @@ -264,12 +278,7 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n id: 'mode', title: 'Analysis Mode', type: 'dropdown', - options: [ - { label: 'Domain (entire domain)', id: 'domain' }, - { label: 'Prefix (URL prefix)', id: 'prefix' }, - { label: 'Subdomains (include all)', id: 'subdomains' }, - { label: 'Exact (exact URL)', id: 'exact' }, - ], + options: MODE_OPTIONS, value: () => 'domain', condition: { field: 'operation', value: 'ahrefs_organic_keywords' }, mode: 'advanced', @@ -278,15 +287,7 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n id: 'limit', title: 'Limit', type: 'short-input', - placeholder: '100', - condition: { field: 'operation', value: 'ahrefs_organic_keywords' }, - mode: 'advanced', - }, - { - id: 'offset', - title: 'Offset', - type: 'short-input', - placeholder: '0', + placeholder: '1000', condition: { field: 'operation', value: 'ahrefs_organic_keywords' }, mode: 'advanced', }, @@ -297,81 +298,41 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n placeholder: 'YYYY-MM-DD (defaults to today)', condition: { field: 'operation', value: 'ahrefs_organic_keywords' }, mode: 'advanced', - wandConfig: { - enabled: true, - prompt: `Generate a date in YYYY-MM-DD format based on the user's description. -Examples: -- "today" -> Current date in YYYY-MM-DD format -- "yesterday" -> Yesterday's date in YYYY-MM-DD format -- "last week" -> Date 7 days ago in YYYY-MM-DD format -- "beginning of this month" -> First day of current month in YYYY-MM-DD format - -Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, no extra text.`, - placeholder: 'Describe the date (e.g., "yesterday", "last week", "start of month")...', - generationType: 'timestamp', - }, + wandConfig: DATE_WAND_CONFIG, }, - // Top Pages operation inputs + // Organic Competitors operation inputs { id: 'target', - title: 'Target Domain', + title: 'Target Domain/URL', type: 'short-input', placeholder: 'example.com', - condition: { field: 'operation', value: 'ahrefs_top_pages' }, + condition: { field: 'operation', value: 'ahrefs_organic_competitors' }, required: true, }, { id: 'country', title: 'Country', type: 'dropdown', - options: [ - { label: 'United States', id: 'us' }, - { label: 'United Kingdom', id: 'gb' }, - { label: 'Germany', id: 'de' }, - { label: 'France', id: 'fr' }, - { label: 'Spain', id: 'es' }, - { label: 'Italy', id: 'it' }, - { label: 'Canada', id: 'ca' }, - { label: 'Australia', id: 'au' }, - { label: 'Japan', id: 'jp' }, - { label: 'Brazil', id: 'br' }, - { label: 'India', id: 'in' }, - { label: 'Netherlands', id: 'nl' }, - { label: 'Poland', id: 'pl' }, - { label: 'Russia', id: 'ru' }, - { label: 'Mexico', id: 'mx' }, - ], + options: COUNTRY_OPTIONS, value: () => 'us', - condition: { field: 'operation', value: 'ahrefs_top_pages' }, + condition: { field: 'operation', value: 'ahrefs_organic_competitors' }, mode: 'advanced', }, { id: 'mode', title: 'Analysis Mode', type: 'dropdown', - options: [ - { label: 'Domain (entire domain)', id: 'domain' }, - { label: 'Prefix (URL prefix)', id: 'prefix' }, - { label: 'Subdomains (include all)', id: 'subdomains' }, - ], + options: MODE_OPTIONS, value: () => 'domain', - condition: { field: 'operation', value: 'ahrefs_top_pages' }, + condition: { field: 'operation', value: 'ahrefs_organic_competitors' }, mode: 'advanced', }, { id: 'limit', title: 'Limit', type: 'short-input', - placeholder: '100', - condition: { field: 'operation', value: 'ahrefs_top_pages' }, - mode: 'advanced', - }, - { - id: 'offset', - title: 'Offset', - type: 'short-input', - placeholder: '0', - condition: { field: 'operation', value: 'ahrefs_top_pages' }, + placeholder: '1000', + condition: { field: 'operation', value: 'ahrefs_organic_competitors' }, mode: 'advanced', }, { @@ -379,65 +340,28 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n title: 'Date', type: 'short-input', placeholder: 'YYYY-MM-DD (defaults to today)', - condition: { field: 'operation', value: 'ahrefs_top_pages' }, + condition: { field: 'operation', value: 'ahrefs_organic_competitors' }, mode: 'advanced', - wandConfig: { - enabled: true, - prompt: `Generate a date in YYYY-MM-DD format based on the user's description. -Examples: -- "today" -> Current date in YYYY-MM-DD format -- "yesterday" -> Yesterday's date in YYYY-MM-DD format -- "last week" -> Date 7 days ago in YYYY-MM-DD format -- "beginning of this month" -> First day of current month in YYYY-MM-DD format - -Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, no extra text.`, - placeholder: 'Describe the date (e.g., "yesterday", "last week", "start of month")...', - generationType: 'timestamp', - }, + wandConfig: DATE_WAND_CONFIG, }, - // Keyword Overview operation inputs + // Top Pages operation inputs { - id: 'keyword', - title: 'Keyword', + id: 'target', + title: 'Target Domain', type: 'short-input', - placeholder: 'Enter keyword to analyze', - condition: { field: 'operation', value: 'ahrefs_keyword_overview' }, + placeholder: 'example.com', + condition: { field: 'operation', value: 'ahrefs_top_pages' }, required: true, }, { id: 'country', title: 'Country', type: 'dropdown', - options: [ - { label: 'United States', id: 'us' }, - { label: 'United Kingdom', id: 'gb' }, - { label: 'Germany', id: 'de' }, - { label: 'France', id: 'fr' }, - { label: 'Spain', id: 'es' }, - { label: 'Italy', id: 'it' }, - { label: 'Canada', id: 'ca' }, - { label: 'Australia', id: 'au' }, - { label: 'Japan', id: 'jp' }, - { label: 'Brazil', id: 'br' }, - { label: 'India', id: 'in' }, - { label: 'Netherlands', id: 'nl' }, - { label: 'Poland', id: 'pl' }, - { label: 'Russia', id: 'ru' }, - { label: 'Mexico', id: 'mx' }, - ], + options: COUNTRY_OPTIONS, value: () => 'us', - condition: { field: 'operation', value: 'ahrefs_keyword_overview' }, + condition: { field: 'operation', value: 'ahrefs_top_pages' }, mode: 'advanced', }, - // Broken Backlinks operation inputs - { - id: 'target', - title: 'Target Domain/URL', - type: 'short-input', - placeholder: 'example.com', - condition: { field: 'operation', value: 'ahrefs_broken_backlinks' }, - required: true, - }, { id: 'mode', title: 'Analysis Mode', @@ -446,48 +370,45 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n { label: 'Domain (entire domain)', id: 'domain' }, { label: 'Prefix (URL prefix)', id: 'prefix' }, { label: 'Subdomains (include all)', id: 'subdomains' }, - { label: 'Exact (exact URL)', id: 'exact' }, ], value: () => 'domain', - condition: { field: 'operation', value: 'ahrefs_broken_backlinks' }, + condition: { field: 'operation', value: 'ahrefs_top_pages' }, mode: 'advanced', }, { id: 'limit', title: 'Limit', type: 'short-input', - placeholder: '100', - condition: { field: 'operation', value: 'ahrefs_broken_backlinks' }, + placeholder: '1000', + condition: { field: 'operation', value: 'ahrefs_top_pages' }, mode: 'advanced', }, { - id: 'offset', - title: 'Offset', + id: 'date', + title: 'Date', type: 'short-input', - placeholder: '0', - condition: { field: 'operation', value: 'ahrefs_broken_backlinks' }, + placeholder: 'YYYY-MM-DD (defaults to today)', + condition: { field: 'operation', value: 'ahrefs_top_pages' }, mode: 'advanced', + wandConfig: DATE_WAND_CONFIG, }, + // Keyword Overview operation inputs { - id: 'date', - title: 'Date', + id: 'keyword', + title: 'Keyword', type: 'short-input', - placeholder: 'YYYY-MM-DD (defaults to today)', - condition: { field: 'operation', value: 'ahrefs_broken_backlinks' }, + placeholder: 'Enter keyword to analyze', + condition: { field: 'operation', value: 'ahrefs_keyword_overview' }, + required: true, + }, + { + id: 'country', + title: 'Country', + type: 'dropdown', + options: COUNTRY_OPTIONS, + value: () => 'us', + condition: { field: 'operation', value: 'ahrefs_keyword_overview' }, mode: 'advanced', - wandConfig: { - enabled: true, - prompt: `Generate a date in YYYY-MM-DD format based on the user's description. -Examples: -- "today" -> Current date in YYYY-MM-DD format -- "yesterday" -> Yesterday's date in YYYY-MM-DD format -- "last week" -> Date 7 days ago in YYYY-MM-DD format -- "beginning of this month" -> First day of current month in YYYY-MM-DD format - -Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, no extra text.`, - placeholder: 'Describe the date (e.g., "yesterday", "last week", "start of month")...', - generationType: 'timestamp', - }, }, // API Key (common to all operations) { @@ -502,33 +423,39 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n tools: { access: [ 'ahrefs_domain_rating', + 'ahrefs_metrics', 'ahrefs_backlinks', 'ahrefs_backlinks_stats', 'ahrefs_referring_domains', + 'ahrefs_broken_backlinks', 'ahrefs_organic_keywords', + 'ahrefs_organic_competitors', 'ahrefs_top_pages', 'ahrefs_keyword_overview', - 'ahrefs_broken_backlinks', ], config: { tool: (params) => { switch (params.operation) { case 'ahrefs_domain_rating': return 'ahrefs_domain_rating' + case 'ahrefs_metrics': + return 'ahrefs_metrics' case 'ahrefs_backlinks': return 'ahrefs_backlinks' case 'ahrefs_backlinks_stats': return 'ahrefs_backlinks_stats' case 'ahrefs_referring_domains': return 'ahrefs_referring_domains' + case 'ahrefs_broken_backlinks': + return 'ahrefs_broken_backlinks' case 'ahrefs_organic_keywords': return 'ahrefs_organic_keywords' + case 'ahrefs_organic_competitors': + return 'ahrefs_organic_competitors' case 'ahrefs_top_pages': return 'ahrefs_top_pages' case 'ahrefs_keyword_overview': return 'ahrefs_keyword_overview' - case 'ahrefs_broken_backlinks': - return 'ahrefs_broken_backlinks' default: return 'ahrefs_domain_rating' } @@ -536,7 +463,6 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n params: (params) => { const result: Record = {} if (params.limit) result.limit = Number(params.limit) - if (params.offset) result.offset = Number(params.offset) return result }, }, @@ -549,27 +475,46 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n mode: { type: 'string', description: 'Analysis mode (domain, prefix, subdomains, exact)' }, country: { type: 'string', description: 'Country code for geo-specific data' }, date: { type: 'string', description: 'Date for historical data in YYYY-MM-DD format' }, + history: { + type: 'string', + description: 'Historical scope for backlink-profile endpoints (all_time, live)', + }, limit: { type: 'number', description: 'Maximum number of results to return' }, - offset: { type: 'number', description: 'Number of results to skip for pagination' }, }, outputs: { // Domain Rating output domainRating: { type: 'number', description: 'Domain Rating score (0-100)' }, ahrefsRank: { type: 'number', description: 'Ahrefs Rank (global ranking)' }, + // Metrics output + metrics: { + type: 'json', + description: + 'Organic and paid search overview (organicTraffic, organicKeywords, organicKeywordsTop3, organicCost, paidTraffic, paidKeywords, paidPages, paidCost)', + }, // Backlinks output backlinks: { type: 'json', description: 'List of backlinks' }, // Backlinks Stats output - stats: { type: 'json', description: 'Backlink statistics' }, + stats: { + type: 'json', + description: + 'Backlink and referring domain totals (liveBacklinks, liveReferringDomains, allTimeBacklinks, allTimeReferringDomains)', + }, // Referring Domains output referringDomains: { type: 'json', description: 'List of referring domains' }, + // Broken Backlinks output + brokenBacklinks: { type: 'json', description: 'List of broken backlinks' }, // Organic Keywords output keywords: { type: 'json', description: 'List of organic keywords' }, + // Organic Competitors output + competitors: { type: 'json', description: 'List of organic search competitors' }, // Top Pages output pages: { type: 'json', description: 'List of top pages' }, // Keyword Overview output - overview: { type: 'json', description: 'Keyword metrics overview' }, - // Broken Backlinks output - brokenBacklinks: { type: 'json', description: 'List of broken backlinks' }, + overview: { + type: 'json', + description: + 'Keyword metrics overview, including search intent flags (informational, navigational, commercial, transactional, branded, local)', + }, }, } @@ -615,6 +560,16 @@ export const AhrefsBlockMeta = { category: 'marketing', tags: ['marketing', 'automation'], }, + { + icon: AhrefsIcon, + title: 'Ahrefs organic competitor finder', + prompt: + 'Build a monthly workflow that pulls Ahrefs organic competitors for my domain, cross-references them against my tracked competitor list, and posts newly surfaced competitors to Slack for review.', + modules: ['scheduled', 'agent', 'workflows'], + category: 'marketing', + tags: ['marketing', 'research'], + alsoIntegrations: ['slack'], + }, { icon: AhrefsIcon, title: 'Ahrefs + Similarweb growth scoreboard', @@ -668,5 +623,12 @@ export const AhrefsBlockMeta = { content: '# Track Organic Rankings\n\nReport how a domain is ranking in organic search using Ahrefs.\n\n## Steps\n1. Pull the organic keywords report for the target domain.\n2. Identify the top-ranking keywords and their positions.\n3. Compare against a prior snapshot if available to find gains and losses.\n\n## Output\nA summary of top organic keywords, notable position gains and drops, and pages that may need attention.', }, + { + name: 'find-organic-competitors', + description: + 'Use Ahrefs organic competitors data to identify sites competing for the same search traffic.', + content: + '# Find Organic Competitors\n\nSurface who actually competes with a domain in organic search using Ahrefs.\n\n## Steps\n1. Run an organic competitors report for the target domain.\n2. Rank results by common keyword overlap and competitor traffic.\n3. Cross-reference against the known competitor list to flag new entrants.\n\n## Output\nA ranked list of organic competitors with keyword overlap and traffic, highlighting any that are not yet being tracked.', + }, ], } as const satisfies BlockMeta diff --git a/apps/sim/tools/ahrefs/backlinks.ts b/apps/sim/tools/ahrefs/backlinks.ts index e5ce1551280..783cc09110b 100644 --- a/apps/sim/tools/ahrefs/backlinks.ts +++ b/apps/sim/tools/ahrefs/backlinks.ts @@ -1,6 +1,9 @@ import type { AhrefsBacklinksParams, AhrefsBacklinksResponse } from '@/tools/ahrefs/types' import type { ToolConfig } from '@/tools/types' +const SELECT_FIELDS = + 'url_from,url_to,anchor,domain_rating_source,is_dofollow,first_seen,last_visited' + export const backlinksTool: ToolConfig = { id: 'ahrefs_backlinks', name: 'Ahrefs Backlinks', @@ -21,25 +24,20 @@ export const backlinksTool: ToolConfig { - const url = new URL('https://api.ahrefs.com/v3/site-explorer/backlinks') + const url = new URL('https://api.ahrefs.com/v3/site-explorer/all-backlinks') url.searchParams.set('target', params.target) - // Date is required - default to today if not provided - const date = params.date || new Date().toISOString().split('T')[0] - url.searchParams.set('date', date) + url.searchParams.set('select', SELECT_FIELDS) if (params.mode) url.searchParams.set('mode', params.mode) + url.searchParams.set('history', params.history || 'all_time') if (params.limit) url.searchParams.set('limit', String(params.limit)) - if (params.offset) url.searchParams.set('offset', String(params.offset)) return url.toString() }, method: 'GET', @@ -79,8 +75,8 @@ export const backlinksTool: ToolConfig { const url = new URL('https://api.ahrefs.com/v3/site-explorer/broken-backlinks') url.searchParams.set('target', params.target) - // Date is required - default to today if not provided - const date = params.date || new Date().toISOString().split('T')[0] - url.searchParams.set('date', date) + url.searchParams.set('select', SELECT_FIELDS) if (params.mode) url.searchParams.set('mode', params.mode) if (params.limit) url.searchParams.set('limit', String(params.limit)) - if (params.offset) url.searchParams.set('offset', String(params.offset)) return url.toString() }, method: 'GET', @@ -81,12 +68,12 @@ export const brokenBacklinksTool: ToolConfig< throw new Error(data.error?.message || data.error || 'Failed to get broken backlinks') } - const brokenBacklinks = (data.backlinks || data.broken_backlinks || []).map((link: any) => ({ + const brokenBacklinks = (data.backlinks || []).map((link: any) => ({ urlFrom: link.url_from || '', urlTo: link.url_to || '', - httpCode: link.http_code ?? link.status_code ?? 404, + httpCode: link.http_code_target ?? null, anchor: link.anchor || '', - domainRatingSource: link.domain_rating_source ?? link.domain_rating ?? 0, + domainRatingSource: link.domain_rating_source ?? 0, })) return { @@ -109,7 +96,11 @@ export const brokenBacklinksTool: ToolConfig< description: 'The URL of the page containing the broken link', }, urlTo: { type: 'string', description: 'The broken URL being linked to' }, - httpCode: { type: 'number', description: 'HTTP status code (e.g., 404, 410)' }, + httpCode: { + type: 'number', + description: 'HTTP status code of the broken target URL (e.g., 404, 410)', + optional: true, + }, anchor: { type: 'string', description: 'The anchor text of the link' }, domainRatingSource: { type: 'number', diff --git a/apps/sim/tools/ahrefs/domain_rating.ts b/apps/sim/tools/ahrefs/domain_rating.ts index 75066ae0c5d..3b3378c9079 100644 --- a/apps/sim/tools/ahrefs/domain_rating.ts +++ b/apps/sim/tools/ahrefs/domain_rating.ts @@ -55,8 +55,8 @@ export const domainRatingTool: ToolConfig { const url = new URL('https://api.ahrefs.com/v3/keywords-explorer/overview') - url.searchParams.set('keyword', params.keyword) + url.searchParams.set('keywords', params.keyword) url.searchParams.set('country', params.country || 'us') + url.searchParams.set('select', SELECT_FIELDS) return url.toString() }, method: 'GET', @@ -56,18 +60,21 @@ export const keywordOverviewTool: ToolConfig< throw new Error(data.error?.message || data.error || 'Failed to get keyword overview') } + const result = (data.keywords || [])[0] || {} + return { success: true, output: { overview: { - keyword: data.keyword || '', - searchVolume: data.volume ?? 0, - keywordDifficulty: data.keyword_difficulty ?? data.difficulty ?? 0, - cpc: data.cpc ?? 0, - clicks: data.clicks ?? 0, - clicksPercentage: data.clicks_percentage ?? 0, - parentTopic: data.parent_topic || '', - trafficPotential: data.traffic_potential ?? 0, + keyword: result.keyword || '', + searchVolume: result.volume ?? 0, + keywordDifficulty: result.difficulty ?? null, + cpc: result.cpc ?? null, + clicks: result.clicks ?? null, + clicksPercentage: result.searches_pct_clicks_organic_only ?? null, + parentTopic: result.parent_topic ?? null, + trafficPotential: result.traffic_potential ?? null, + intents: result.intents ?? null, }, }, } @@ -83,17 +90,38 @@ export const keywordOverviewTool: ToolConfig< keywordDifficulty: { type: 'number', description: 'Keyword difficulty score (0-100)', + optional: true, }, - cpc: { type: 'number', description: 'Cost per click in USD' }, - clicks: { type: 'number', description: 'Estimated clicks per month' }, + cpc: { type: 'number', description: 'Cost per click in USD', optional: true }, + clicks: { type: 'number', description: 'Estimated clicks per month', optional: true }, clicksPercentage: { type: 'number', - description: 'Percentage of searches that result in clicks', + description: 'Percentage of searches that result in an organic click', + optional: true, + }, + parentTopic: { + type: 'string', + description: 'The parent topic for this keyword', + optional: true, }, - parentTopic: { type: 'string', description: 'The parent topic for this keyword' }, trafficPotential: { type: 'number', description: 'Estimated traffic potential if ranking #1', + optional: true, + }, + intents: { + type: 'object', + description: + 'Search intent flags (informational, navigational, commercial, transactional, branded, local)', + optional: true, + properties: { + informational: { type: 'boolean', description: 'Query seeks information' }, + navigational: { type: 'boolean', description: 'Query seeks a specific site or page' }, + commercial: { type: 'boolean', description: 'Query researches a purchase decision' }, + transactional: { type: 'boolean', description: 'Query intends to complete a purchase' }, + branded: { type: 'boolean', description: 'Query references a specific brand' }, + local: { type: 'boolean', description: 'Query seeks local results' }, + }, }, }, }, diff --git a/apps/sim/tools/ahrefs/metrics.ts b/apps/sim/tools/ahrefs/metrics.ts new file mode 100644 index 00000000000..99184349d74 --- /dev/null +++ b/apps/sim/tools/ahrefs/metrics.ts @@ -0,0 +1,116 @@ +import type { AhrefsMetricsParams, AhrefsMetricsResponse } from '@/tools/ahrefs/types' +import type { ToolConfig } from '@/tools/types' + +export const metricsTool: ToolConfig = { + id: 'ahrefs_metrics', + name: 'Ahrefs Metrics', + description: + 'Get a one-call organic and paid search overview for a target domain or URL: organic traffic, organic keywords, paid traffic, paid keywords, and estimated traffic cost.', + version: '1.0.0', + + params: { + target: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The target domain or URL to analyze. Example: "example.com"', + }, + country: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Country code for traffic data. Example: "us", "gb", "de"', + }, + mode: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: + 'Analysis mode: domain (entire domain), prefix (URL prefix), subdomains (include all subdomains, default), exact (exact URL match). Example: "domain"', + }, + date: { + type: 'string', + required: false, + visibility: 'user-only', + description: 'Date to report metrics on, in YYYY-MM-DD format (defaults to today)', + }, + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Ahrefs API Key', + }, + }, + + request: { + url: (params) => { + const url = new URL('https://api.ahrefs.com/v3/site-explorer/metrics') + url.searchParams.set('target', params.target) + // Date is required - default to today if not provided + const date = params.date || new Date().toISOString().split('T')[0] + url.searchParams.set('date', date) + url.searchParams.set('country', params.country || 'us') + if (params.mode) url.searchParams.set('mode', params.mode) + return url.toString() + }, + method: 'GET', + headers: (params) => ({ + Accept: 'application/json', + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response: Response) => { + const data = await response.json() + + if (!response.ok) { + throw new Error(data.error?.message || data.error || 'Failed to get metrics') + } + + const metrics = data.metrics || {} + + return { + success: true, + output: { + metrics: { + organicTraffic: metrics.org_traffic ?? 0, + organicKeywords: metrics.org_keywords ?? 0, + organicKeywordsTop3: metrics.org_keywords_1_3 ?? 0, + organicCost: metrics.org_cost ?? null, + paidTraffic: metrics.paid_traffic ?? 0, + paidKeywords: metrics.paid_keywords ?? 0, + paidPages: metrics.paid_pages ?? 0, + paidCost: metrics.paid_cost ?? null, + }, + }, + } + }, + + outputs: { + metrics: { + type: 'object', + description: 'Organic and paid search overview', + properties: { + organicTraffic: { type: 'number', description: 'Estimated monthly organic traffic' }, + organicKeywords: { type: 'number', description: 'Number of organic keywords ranked' }, + organicKeywordsTop3: { + type: 'number', + description: 'Number of organic keywords ranking in positions 1-3', + }, + organicCost: { + type: 'number', + description: 'Estimated monthly cost to replicate organic traffic via ads (USD)', + optional: true, + }, + paidTraffic: { type: 'number', description: 'Estimated monthly paid search traffic' }, + paidKeywords: { type: 'number', description: 'Number of paid keywords targeted' }, + paidPages: { type: 'number', description: 'Number of pages receiving paid traffic' }, + paidCost: { + type: 'number', + description: 'Estimated monthly paid search spend (USD)', + optional: true, + }, + }, + }, + }, +} diff --git a/apps/sim/tools/ahrefs/organic_competitors.ts b/apps/sim/tools/ahrefs/organic_competitors.ts new file mode 100644 index 00000000000..e304f567d0e --- /dev/null +++ b/apps/sim/tools/ahrefs/organic_competitors.ts @@ -0,0 +1,138 @@ +import type { + AhrefsOrganicCompetitorsParams, + AhrefsOrganicCompetitorsResponse, +} from '@/tools/ahrefs/types' +import type { ToolConfig } from '@/tools/types' + +const SELECT_FIELDS = + 'competitor_domain,domain_rating,keywords_common,keywords_target,keywords_competitor,traffic' + +export const organicCompetitorsTool: ToolConfig< + AhrefsOrganicCompetitorsParams, + AhrefsOrganicCompetitorsResponse +> = { + id: 'ahrefs_organic_competitors', + name: 'Ahrefs Organic Competitors', + description: + 'Get domains that compete with a target domain or URL for the same organic keywords, ranked by keyword overlap.', + version: '1.0.0', + + params: { + target: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The target domain or URL to analyze. Example: "example.com"', + }, + country: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Country code for search results. Example: "us", "gb", "de" (default: "us")', + }, + mode: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: + 'Analysis mode: domain (entire domain), prefix (URL prefix), subdomains (include all subdomains, default), exact (exact URL match). Example: "domain"', + }, + date: { + type: 'string', + required: false, + visibility: 'user-only', + description: 'Date to report metrics on, in YYYY-MM-DD format (defaults to today)', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of results to return. Example: 50 (default: 1000)', + }, + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Ahrefs API Key', + }, + }, + + request: { + url: (params) => { + const url = new URL('https://api.ahrefs.com/v3/site-explorer/organic-competitors') + url.searchParams.set('target', params.target) + url.searchParams.set('country', params.country || 'us') + url.searchParams.set('select', SELECT_FIELDS) + // Date is required - default to today if not provided + const date = params.date || new Date().toISOString().split('T')[0] + url.searchParams.set('date', date) + if (params.mode) url.searchParams.set('mode', params.mode) + if (params.limit) url.searchParams.set('limit', String(params.limit)) + return url.toString() + }, + method: 'GET', + headers: (params) => ({ + Accept: 'application/json', + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response: Response) => { + const data = await response.json() + + if (!response.ok) { + throw new Error(data.error?.message || data.error || 'Failed to get organic competitors') + } + + const competitors = (data.competitors || []).map((competitor: any) => ({ + domain: competitor.competitor_domain ?? null, + domainRating: competitor.domain_rating ?? 0, + commonKeywords: competitor.keywords_common ?? 0, + targetKeywords: competitor.keywords_target ?? 0, + competitorKeywords: competitor.keywords_competitor ?? 0, + traffic: competitor.traffic ?? null, + })) + + return { + success: true, + output: { + competitors, + }, + } + }, + + outputs: { + competitors: { + type: 'array', + description: 'List of organic search competitors ranked by keyword overlap', + items: { + type: 'object', + properties: { + domain: { + type: 'string', + description: 'The competitor domain', + optional: true, + }, + domainRating: { type: 'number', description: 'Domain Rating of the competitor' }, + commonKeywords: { + type: 'number', + description: 'Number of keywords the competitor and target both rank for', + }, + targetKeywords: { + type: 'number', + description: 'Number of keywords the target ranks for', + }, + competitorKeywords: { + type: 'number', + description: 'Number of keywords the competitor ranks for', + }, + traffic: { + type: 'number', + description: 'Estimated monthly organic traffic for the competitor', + optional: true, + }, + }, + }, + }, + }, +} diff --git a/apps/sim/tools/ahrefs/organic_keywords.ts b/apps/sim/tools/ahrefs/organic_keywords.ts index 3565b901c8b..73ff0e0a4f2 100644 --- a/apps/sim/tools/ahrefs/organic_keywords.ts +++ b/apps/sim/tools/ahrefs/organic_keywords.ts @@ -4,6 +4,9 @@ import type { } from '@/tools/ahrefs/types' import type { ToolConfig } from '@/tools/types' +const SELECT_FIELDS = + 'keyword,volume,best_position,best_position_url,sum_traffic,keyword_difficulty' + export const organicKeywordsTool: ToolConfig< AhrefsOrganicKeywordsParams, AhrefsOrganicKeywordsResponse @@ -33,25 +36,19 @@ export const organicKeywordsTool: ToolConfig< required: false, visibility: 'user-or-llm', description: - 'Analysis mode: domain (entire domain), prefix (URL prefix), subdomains (include all subdomains), exact (exact URL match). Example: "domain"', + 'Analysis mode: domain (entire domain), prefix (URL prefix), subdomains (include all subdomains, default), exact (exact URL match). Example: "domain"', }, date: { type: 'string', required: false, visibility: 'user-only', - description: 'Date for historical data in YYYY-MM-DD format (defaults to today)', + description: 'Date to report metrics on, in YYYY-MM-DD format (defaults to today)', }, limit: { type: 'number', required: false, visibility: 'user-or-llm', - description: 'Maximum number of results to return. Example: 50 (default: 100)', - }, - offset: { - type: 'number', - required: false, - visibility: 'user-or-llm', - description: 'Number of results to skip for pagination. Example: 100', + description: 'Maximum number of results to return. Example: 50 (default: 1000)', }, apiKey: { type: 'string', @@ -66,12 +63,12 @@ export const organicKeywordsTool: ToolConfig< const url = new URL('https://api.ahrefs.com/v3/site-explorer/organic-keywords') url.searchParams.set('target', params.target) url.searchParams.set('country', params.country || 'us') + url.searchParams.set('select', SELECT_FIELDS) // Date is required - default to today if not provided const date = params.date || new Date().toISOString().split('T')[0] url.searchParams.set('date', date) if (params.mode) url.searchParams.set('mode', params.mode) if (params.limit) url.searchParams.set('limit', String(params.limit)) - if (params.offset) url.searchParams.set('offset', String(params.offset)) return url.toString() }, method: 'GET', @@ -88,13 +85,13 @@ export const organicKeywordsTool: ToolConfig< throw new Error(data.error?.message || data.error || 'Failed to get organic keywords') } - const keywords = (data.keywords || data.organic_keywords || []).map((kw: any) => ({ + const keywords = (data.keywords || []).map((kw: any) => ({ keyword: kw.keyword || '', volume: kw.volume ?? 0, - position: kw.position ?? 0, - url: kw.url || '', - traffic: kw.traffic ?? 0, - keywordDifficulty: kw.keyword_difficulty ?? kw.difficulty ?? 0, + position: kw.best_position ?? null, + url: kw.best_position_url ?? null, + traffic: kw.sum_traffic ?? 0, + keywordDifficulty: kw.keyword_difficulty ?? null, })) return { @@ -114,12 +111,21 @@ export const organicKeywordsTool: ToolConfig< properties: { keyword: { type: 'string', description: 'The keyword' }, volume: { type: 'number', description: 'Monthly search volume' }, - position: { type: 'number', description: 'Current ranking position' }, - url: { type: 'string', description: 'The URL that ranks for this keyword' }, + position: { + type: 'number', + description: 'Best ranking position for this keyword', + optional: true, + }, + url: { + type: 'string', + description: 'The URL that ranks at the best position for this keyword', + optional: true, + }, traffic: { type: 'number', description: 'Estimated monthly organic traffic' }, keywordDifficulty: { type: 'number', description: 'Keyword difficulty score (0-100)', + optional: true, }, }, }, diff --git a/apps/sim/tools/ahrefs/referring_domains.ts b/apps/sim/tools/ahrefs/referring_domains.ts index 87a21367c52..f6120d1a4bf 100644 --- a/apps/sim/tools/ahrefs/referring_domains.ts +++ b/apps/sim/tools/ahrefs/referring_domains.ts @@ -4,6 +4,8 @@ import type { } from '@/tools/ahrefs/types' import type { ToolConfig } from '@/tools/types' +const SELECT_FIELDS = 'domain,domain_rating,links_to_target,dofollow_links,first_seen,last_seen' + export const referringDomainsTool: ToolConfig< AhrefsReferringDomainsParams, AhrefsReferringDomainsResponse @@ -27,25 +29,20 @@ export const referringDomainsTool: ToolConfig< required: false, visibility: 'user-or-llm', description: - 'Analysis mode: domain (entire domain), prefix (URL prefix), subdomains (include all subdomains), exact (exact URL match). Example: "domain"', + 'Analysis mode: domain (entire domain), prefix (URL prefix), subdomains (include all subdomains, default), exact (exact URL match). Example: "domain"', }, - date: { + history: { type: 'string', required: false, - visibility: 'user-only', - description: 'Date for historical data in YYYY-MM-DD format (defaults to today)', - }, - limit: { - type: 'number', - required: false, visibility: 'user-or-llm', - description: 'Maximum number of results to return. Example: 50 (default: 100)', + description: + 'Historical scope: "live" (currently live), "all_time" (default, includes lost domains), or "since:YYYY-MM-DD" (domains found since a date).', }, - offset: { + limit: { type: 'number', required: false, visibility: 'user-or-llm', - description: 'Number of results to skip for pagination. Example: 100', + description: 'Maximum number of results to return. Example: 50 (default: 1000)', }, apiKey: { type: 'string', @@ -59,12 +56,10 @@ export const referringDomainsTool: ToolConfig< url: (params) => { const url = new URL('https://api.ahrefs.com/v3/site-explorer/refdomains') url.searchParams.set('target', params.target) - // Date is required - default to today if not provided - const date = params.date || new Date().toISOString().split('T')[0] - url.searchParams.set('date', date) + url.searchParams.set('select', SELECT_FIELDS) if (params.mode) url.searchParams.set('mode', params.mode) + url.searchParams.set('history', params.history || 'all_time') if (params.limit) url.searchParams.set('limit', String(params.limit)) - if (params.offset) url.searchParams.set('offset', String(params.offset)) return url.toString() }, method: 'GET', @@ -81,16 +76,14 @@ export const referringDomainsTool: ToolConfig< throw new Error(data.error?.message || data.error || 'Failed to get referring domains') } - const referringDomains = (data.refdomains || data.referring_domains || []).map( - (domain: any) => ({ - domain: domain.domain || domain.refdomain || '', - domainRating: domain.domain_rating ?? 0, - backlinks: domain.backlinks ?? 0, - dofollowBacklinks: domain.dofollow_backlinks ?? domain.dofollow ?? 0, - firstSeen: domain.first_seen || '', - lastVisited: domain.last_visited || '', - }) - ) + const referringDomains = (data.refdomains || []).map((domain: any) => ({ + domain: domain.domain || '', + domainRating: domain.domain_rating ?? 0, + backlinks: domain.links_to_target ?? 0, + dofollowBacklinks: domain.dofollow_links ?? 0, + firstSeen: domain.first_seen || '', + lastVisited: domain.last_seen ?? null, + })) return { success: true, @@ -111,14 +104,18 @@ export const referringDomainsTool: ToolConfig< domainRating: { type: 'number', description: 'Domain Rating of the referring domain' }, backlinks: { type: 'number', - description: 'Total number of backlinks from this domain', + description: 'Total number of backlinks from this domain to the target', }, dofollowBacklinks: { type: 'number', description: 'Number of dofollow backlinks from this domain', }, firstSeen: { type: 'string', description: 'When the domain was first seen linking' }, - lastVisited: { type: 'string', description: 'When the domain was last checked' }, + lastVisited: { + type: 'string', + description: 'When the domain was last seen linking (null if never re-crawled)', + optional: true, + }, }, }, }, diff --git a/apps/sim/tools/ahrefs/top_pages.ts b/apps/sim/tools/ahrefs/top_pages.ts index bb48d8cf0d0..9feb05c40b6 100644 --- a/apps/sim/tools/ahrefs/top_pages.ts +++ b/apps/sim/tools/ahrefs/top_pages.ts @@ -1,6 +1,8 @@ import type { AhrefsTopPagesParams, AhrefsTopPagesResponse } from '@/tools/ahrefs/types' import type { ToolConfig } from '@/tools/types' +const SELECT_FIELDS = 'url,sum_traffic,keywords,top_keyword,value' + export const topPagesTool: ToolConfig = { id: 'ahrefs_top_pages', name: 'Ahrefs Top Pages', @@ -26,32 +28,19 @@ export const topPagesTool: ToolConfig ({ - url: page.url || '', - traffic: page.traffic ?? 0, - keywords: page.keywords ?? page.keyword_count ?? 0, - topKeyword: page.top_keyword || '', - value: page.value ?? page.traffic_value ?? 0, + const pages = (data.pages || []).map((page: any) => ({ + url: page.url ?? null, + traffic: page.sum_traffic ?? 0, + keywords: page.keywords ?? null, + topKeyword: page.top_keyword ?? null, + value: page.value ?? null, })) return { @@ -114,14 +100,23 @@ export const topPagesTool: ToolConfig = { attio_update_record: attioUpdateRecordTool, attio_update_task: attioUpdateTaskTool, attio_update_webhook: attioUpdateWebhookTool, - ahrefs_domain_rating: ahrefsDomainRatingTool, ahrefs_backlinks: ahrefsBacklinksTool, ahrefs_backlinks_stats: ahrefsBacklinksStatsTool, - ahrefs_referring_domains: ahrefsReferringDomainsTool, + ahrefs_broken_backlinks: ahrefsBrokenBacklinksTool, + ahrefs_domain_rating: ahrefsDomainRatingTool, + ahrefs_keyword_overview: ahrefsKeywordOverviewTool, + ahrefs_metrics: ahrefsMetricsTool, + ahrefs_organic_competitors: ahrefsOrganicCompetitorsTool, ahrefs_organic_keywords: ahrefsOrganicKeywordsTool, + ahrefs_referring_domains: ahrefsReferringDomainsTool, ahrefs_top_pages: ahrefsTopPagesTool, - ahrefs_keyword_overview: ahrefsKeywordOverviewTool, - ahrefs_broken_backlinks: ahrefsBrokenBacklinksTool, apify_run_actor_sync: apifyRunActorSyncTool, apify_run_actor_async: apifyRunActorAsyncTool, apify_run_task: apifyRunTaskTool,