analyzeFollowerDemographics
Analyze Twitter follower demographics and engagement patterns to understand audience composition and interaction trends for strategic insights.
Instructions
Analyze follower demographics and engagement patterns
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| username | Yes | Username to analyze followers for | |
| sampleSize | No | Sample size for analysis (default: 50) | |
| analyzeDemographics | No | Include demographic breakdown (default: true) |
Implementation Reference
- The main handler function that implements the core logic for analyzing follower demographics by sampling user interactions (mentions) with the target account, computing statistics like verified percentage, average followers, distribution categories, and top interactors.export const handleAnalyzeFollowerDemographics: SocialDataHandler<FollowerAnalyticsArgs> = async ( _client: any, { username, sampleSize = 50, analyzeDemographics = true }: FollowerAnalyticsArgs ) => { try { const socialClient = getSocialDataClient(); if (!socialClient) { return createMissingApiKeyResponse('Follower Demographics Analysis'); } // Get recent interactions to sample follower activity const mentionsQuery = `@${username}`; const mentionsResult = await socialClient.searchTweets({ query: mentionsQuery, maxResults: sampleSize }); // Get retweets of user's content const retweetsQuery = `from:${username}`; const userTweetsResult = await socialClient.searchTweets({ query: retweetsQuery, maxResults: 25 }); const interactingUsers = new Map(); // Analyze users who mention this account mentionsResult.data?.forEach((tweet: any) => { const user = tweet.user; if (user && user.screen_name !== username) { interactingUsers.set(user.screen_name, { screen_name: user.screen_name, name: user.name, followers_count: user.followers_count, verified: user.verified, interaction_type: 'mention' }); } }); const sampleUsers = Array.from(interactingUsers.values()); let analytics: any = { target_user: username, sample_size: sampleUsers.length, analysis_date: new Date().toISOString() }; if (analyzeDemographics && sampleUsers.length > 0) { const verifiedCount = sampleUsers.filter(u => u.verified).length; const followerCounts = sampleUsers.map(u => u.followers_count || 0); const avgFollowers = followerCounts.reduce((a, b) => a + b, 0) / followerCounts.length; analytics.demographics = { verified_percentage: Math.round((verifiedCount / sampleUsers.length) * 100), average_follower_count: Math.round(avgFollowers), follower_distribution: { micro_influencers: followerCounts.filter(c => c >= 1000 && c < 100000).length, regular_users: followerCounts.filter(c => c < 1000).length, large_accounts: followerCounts.filter(c => c >= 100000).length }, engagement_quality: sampleUsers.length > 20 ? 'High' : sampleUsers.length > 10 ? 'Medium' : 'Low' }; analytics.top_interacting_users = sampleUsers .sort((a, b) => (b.followers_count || 0) - (a.followers_count || 0)) .slice(0, 10) .map(u => ({ username: u.screen_name, name: u.name, followers: u.followers_count, verified: u.verified })); } return createSocialDataResponse( formatAnalytics(analytics, `Follower Demographics Analysis for @${username}`) ); } catch (error) { throw new Error(formatSocialDataError(error as Error, 'follower analytics')); } };
- src/socialdata-tools.ts:265-287 (schema)Zod schema definition and input validation structure for the analyzeFollowerDemographics tool, defining required username and optional sampleSize and analyzeDemographics parameters.analyzeFollowerDemographics: { description: 'Analyze follower demographics and engagement patterns', inputSchema: { type: 'object', properties: { username: { type: 'string', description: 'Username to analyze followers for' }, sampleSize: { type: 'number', description: 'Sample size for analysis (default: 50)', minimum: 10, maximum: 100 }, analyzeDemographics: { type: 'boolean', description: 'Include demographic breakdown (default: true)' } }, required: ['username'] } },
- src/index.ts:478-481 (registration)Tool dispatch registration in the main MCP server request handler switch statement, routing 'analyzeFollowerDemographics' tool calls to the specific handler function.case 'analyzeFollowerDemographics': { const args = request.params.arguments as any; response = await handleAnalyzeFollowerDemographics(client, args); break;