DEV Community

Cover image for كيفية استخدام Hootsuite API؟
Yusuf Khalidd
Yusuf Khalidd

Posted on • Originally published at apidog.com

كيفية استخدام Hootsuite API؟

خلاصة القول

تمكنك واجهة برمجة تطبيقات Hootsuite (API) من التكامل مع مهام إدارة وسائل التواصل الاجتماعي برمجيًا، وتستخدم مصادقة OAuth 2.0 ونقاط نهاية RESTful للملفات الشخصية والمنشورات والتحليلات وإدارة الفريق، مع حدود معدل من 50 إلى 200 طلب في الدقيقة حسب الخطة. يوضح هذا الدليل إعداد المصادقة، جدولة المنشورات، استرجاع التحليلات، إدارة الفريق، واستراتيجيات التكامل في الإنتاج.

جرّب Apidog اليوم

ملاحظة: أوقفت Hootsuite دعم الواجهة العامة لبرمجة التطبيقات عام 2024. سنغطي هنا الطرق البديلة، بما يشمل تكاملات شركاء Hootsuite، webhooks، وواجهات برمجة تطبيقات إدارة وسائل التواصل الاجتماعي التابعة لطرف ثالث والتي تمنح نفس الوظائف تقريبًا.

مقدمة

تدير Hootsuite أكثر من 30 مليون حساب على وسائل التواصل الاجتماعي لأكثر من 200,000 شركة في 175+ دولة. إذا كنت مطورًا تبني أدوات لوسائل التواصل الاجتماعي أو منصات تسويقية أو لوحات تحكم تحليلية، فإن التكامل مع واجهات برمجة تطبيقات وسائل التواصل الاجتماعي أمر أساسي للوصول إلى الجمهور التجاري.

الواقع: مدراء وسائل التواصل الاجتماعي الذين يديرون أكثر من 20 حسابًا يضيعون 25-35 ساعة أسبوعيًا في النشر اليدوي وتتبع التفاعل والتقارير. الأتمتة عبر واجهات برمجة التطبيقات توفر توزيع محتوى تلقائي، مراقبة التفاعل، تحليل المشاعر، وتقديم تقارير أداء.

حالة واجهة برمجة تطبيقات Hootsuite والبدائل

الوضع الحالي لواجهة برمجة التطبيقات

منذ 2024، أوقفت Hootsuite دعم API العامة. البدائل المتاحة للتكامل:

النهج الوصف الأفضل لـ
واجهات برمجة التطبيقات للمنصات الأصلية التكامل المباشر مع فيسبوك، تويتر، لينكدإن، إلخ تحكم كامل، حلول مخصصة
Audiense استخبارات الجمهور المملوكة لـ Hootsuite تحليل الجمهور
HeyOrca API لجدولة وسائل التواصل الاجتماعي تقويمات المحتوى
Buffer API إدارة وسائل التواصل الاجتماعي الفرق الصغيرة
Sprout Social API إدارة اجتماعية للمؤسسات المنظمات الكبيرة
Agorapulse API نظام إدارة علاقات العملاء لوسائل التواصل إدارة المجتمع

النهج الموصى به: واجهات برمجة تطبيقات المنصات الأصلية

التكامل المباشر مع كل منصة اجتماعية يمنحك أقصى مرونة للتحكم في النشر والتحليلات. فيما يلي ملخص للمنصات وواجهاتها:

المنصة اسم API الميزات الرئيسية
فيسبوك/انستغرام Graph API المنشورات، الرؤى، التعليقات
تويتر/إكس API v2 التغريدات، التحليلات، التدفقات
لينكدإن Marketing API المنشورات، صفحات الشركات، الإعلانات
بينتيريست API v5 Pins، اللوحات، التحليلات
تيك توك Display API الفيديوهات، معلومات المستخدم
يوتيوب Data API الفيديوهات، قوائم التشغيل، التحليلات

البدء: مصادقة متعددة المنصات

الخطوة 1: تسجيل تطبيقات المطورين

سجّل تطبيقًا لكل منصة واحفظ بيانات الاعتماد بأمان:

// تخزين بيانات الاعتماد بأمان
const SOCIAL_CREDENTIALS = {
  facebook: {
    appId: process.env.FB_APP_ID,
    appSecret: process.env.FB_APP_SECRET,
    redirectUri: process.env.FB_REDIRECT_URI
  },
  twitter: {
    apiKey: process.env.TWITTER_API_KEY,
    apiSecret: process.env.TWITTER_API_SECRET,
    redirectUri: process.env.TWITTER_REDIRECT_URI
  },
  linkedin: {
    clientId: process.env.LINKEDIN_CLIENT_ID,
    clientSecret: process.env.LINKEDIN_CLIENT_SECRET,
    redirectUri: process.env.LINKEDIN_REDIRECT_URI
  },
  instagram: {
    appId: process.env.FB_APP_ID, // يستخدم تسجيل الدخول عبر فيسبوك
    appSecret: process.env.FB_APP_SECRET
  }
};
Enter fullscreen mode Exit fullscreen mode

الخطوة 2: تطبيق تدفق OAuth 2.0

بناء معالج OAuth موحد لكل المنصات:

const getAuthUrl = (platform, state) => {
  const configs = {
    facebook: {
      url: 'https://www.facebook.com/v18.0/dialog/oauth',
      params: {
        client_id: SOCIAL_CREDENTIALS.facebook.appId,
        redirect_uri: SOCIAL_CREDENTIALS.facebook.redirectUri,
        scope: 'pages_manage_posts,pages_read_engagement,instagram_basic,instagram_content_publish',
        state
      }
    },
    twitter: {
      url: 'https://twitter.com/i/oauth2/authorize',
      params: {
        client_id: SOCIAL_CREDENTIALS.twitter.apiKey,
        redirect_uri: SOCIAL_CREDENTIALS.twitter.redirectUri,
        scope: 'tweet.read tweet.write users.read offline.access',
        state,
        response_type: 'code'
      }
    },
    linkedin: {
      url: 'https://www.linkedin.com/oauth/v2/authorization',
      params: {
        client_id: SOCIAL_CREDENTIALS.linkedin.clientId,
        redirect_uri: SOCIAL_CREDENTIALS.linkedin.redirectUri,
        scope: 'w_member_social r_basicprofile',
        state,
        response_type: 'code'
      }
    }
  };

  const config = configs[platform];
  const params = new URLSearchParams(config.params);
  return `${config.url}?${params.toString()}`;
};

// معالجة رد نداء OAuth
const handleOAuthCallback = async (platform, code) => {
  const tokenEndpoints = {
    facebook: 'https://graph.facebook.com/v18.0/oauth/access_token',
    twitter: 'https://api.twitter.com/2/oauth2/token',
    linkedin: 'https://www.linkedin.com/oauth/v2/accessToken'
  };

  const response = await fetch(tokenEndpoints[platform], {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: new URLSearchParams({
      client_id: SOCIAL_CREDENTIALS[platform].apiKey || SOCIAL_CREDENTIALS[platform].appId || SOCIAL_CREDENTIALS[platform].clientId,
      client_secret: SOCIAL_CREDENTIALS[platform].appSecret || SOCIAL_CREDENTIALS[platform].apiSecret,
      redirect_uri: SOCIAL_CREDENTIALS[platform].redirectUri,
      code,
      grant_type: 'authorization_code'
    })
  });

  return response.json();
};
Enter fullscreen mode Exit fullscreen mode

الخطوة 3: تخزين الرموز المميزة (Tokens) بأمان

استخدم قاعدة بيانات مشفرة لتخزين الرموز:

// مخطط قاعدة البيانات لرموز الوسائط الاجتماعية
const SocialToken = {
  userId: 'user_123',
  platform: 'facebook',
  accessToken: 'encrypted_token_here',
  refreshToken: 'encrypted_refresh_token',
  tokenExpiry: Date.now() + 5183999, // 60 يومًا
  scopes: ['pages_manage_posts', 'pages_read_engagement'],
  pageId: 'page_456', // لفيسبوك/انستغرام
  pageName: 'صفحة عملي'
};
Enter fullscreen mode Exit fullscreen mode

جدولة ونشر المنشورات

إنشاء منشور متعدد المنصات

نشر منشور عبر عدة منصات دفعة واحدة:

const createSocialPost = async (postData) => {
  const results = {};

  // منشور صفحة فيسبوك
  if (postData.platforms.includes('facebook')) {
    results.facebook = await postToFacebook({
      pageId: postData.facebookPageId,
      message: postData.message,
      link: postData.link,
      photo: postData.photo
    });
  }

  // منشور تويتر
  if (postData.platforms.includes('twitter')) {
    results.twitter = await postToTwitter({
      text: postData.message,
      media: postData.photo
    });
  }

  // منشور لينكد إن
  if (postData.platforms.includes('linkedin')) {
    results.linkedin = await postToLinkedIn({
      authorUrn: postData.linkedinAuthorUrn,
      text: postData.message,
      contentUrl: postData.link
    });
  }

  // منشور انستغرام
  if (postData.platforms.includes('instagram')) {
    results.instagram = await postToInstagram({
      igAccountId: postData.igAccountId,
      imageUrl: postData.photo,
      caption: postData.message
    });
  }

  return results;
};
Enter fullscreen mode Exit fullscreen mode

أمثلة على وظائف النشر لمنصة محددة (فيسبوك، تويتر، لينكدإن، انستغرام)

// النشر على فيسبوك
const postToFacebook = async (postData) => {
  const token = await getFacebookPageToken(postData.pageId);

  const params = new URLSearchParams({
    message: postData.message,
    access_token: token
  });

  if (postData.link) params.append('link', postData.link);
  if (postData.photo) params.append('photo', postData.photo);

  const response = await fetch(
    `https://graph.facebook.com/v18.0/${postData.pageId}/feed?${params.toString()}`,
    { method: 'POST' }
  );

  return response.json();
};
Enter fullscreen mode Exit fullscreen mode
// النشر على تويتر
const postToTwitter = async (postData) => {
  const token = await getTwitterToken();

  let mediaIds = [];
  if (postData.media) {
    const mediaUpload = await uploadTwitterMedia(postData.media, token);
    mediaIds = [mediaUpload.media_id_string];
  }

  const response = await fetch('https://api.twitter.com/2/tweets', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      text: postData.text,
      media: mediaIds.length > 0 ? { media_ids: mediaIds } : undefined
    })
  });

  return response.json();
};
Enter fullscreen mode Exit fullscreen mode
// النشر على لينكد إن
const postToLinkedIn = async (postData) => {
  const token = await getLinkedInToken();

  const post = {
    author: postData.authorUrn,
    lifecycleState: 'PUBLISHED',
    specificContent: {
      'com.linkedin.ugc.ShareContent': {
        shareCommentary: {
          text: postData.text
        },
        shareMediaCategory: postData.contentUrl ? 'ARTICLE' : 'NONE',
        media: postData.contentUrl ? [{
          status: 'READY',
          media: postData.contentUrn,
          description: { text: postData.text }
        }] : []
      }
    },
    visibility: {
      'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC'
    }
  };

  const response = await fetch('https://api.linkedin.com/v2/ugcPosts', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json',
      'X-Restli-Protocol-Version': '2.0.0'
    },
    body: JSON.stringify(post)
  });

  return response.json();
};
Enter fullscreen mode Exit fullscreen mode
// النشر على انستغرام
const postToInstagram = async (postData) => {
  const token = await getInstagramToken();

  // الخطوة 1: إنشاء حاوية وسائط
  const containerResponse = await fetch(
    `https://graph.facebook.com/v18.0/${postData.igAccountId}/media`,
    {
      method: 'POST',
      headers: { 'Authorization': `Bearer ${token}` },
      body: JSON.stringify({
        image_url: postData.imageUrl,
        caption: postData.caption
      })
    }
  );

  const container = await containerResponse.json();

  // الخطوة 2: النشر
  const publishResponse = await fetch(
    `https://graph.facebook.com/v18.0/${postData.igAccountId}/media_publish`,
    {
      method: 'POST',
      headers: { 'Authorization': `Bearer ${token}` },
      body: JSON.stringify({ creation_id: container.id })
    }
  );

  return publishResponse.json();
};
Enter fullscreen mode Exit fullscreen mode

جدولة المنشورات

لتنفيذ جدولة المنشورات تلقائيًا:

const schedulePost = async (postData, scheduledTime) => {
  // تخزين في قاعدة البيانات للتنفيذ لاحقًا
  const scheduledPost = await db.scheduledPosts.create({
    message: postData.message,
    platforms: postData.platforms,
    scheduledTime: scheduledTime,
    status: 'pending',
    media: postData.media,
    link: postData.link
  });

  // إعداد قائمة انتظار المهام
  await jobQueue.add('publish-social-post', {
    postId: scheduledPost.id
  }, {
    delay: scheduledTime - Date.now()
  });

  return scheduledPost;
};

// معالج المهام
jobQueue.process('publish-social-post', async (job) => {
  const post = await db.scheduledPosts.findById(job.data.postId);

  try {
    const result = await createSocialPost(post);

    await db.scheduledPosts.update(post.id, {
      status: 'published',
      publishedAt: new Date(),
      results: result
    });

    return result;
  } catch (error) {
    await db.scheduledPosts.update(post.id, {
      status: 'failed',
      error: error.message
    });

    throw error;
  }
});
Enter fullscreen mode Exit fullscreen mode

التحليلات والتقارير

جلب تحليلات متعددة المنصات

اجلب المقاييس من كل منصة وادمج النتائج:

const getSocialAnalytics = async (accountId, dateRange) => {
  const analytics = {
    facebook: await getFacebookAnalytics(accountId.facebook, dateRange),
    twitter: await getTwitterAnalytics(accountId.twitter, dateRange),
    linkedin: await getLinkedInAnalytics(accountId.linkedin, dateRange),
    instagram: await getInstagramAnalytics(accountId.instagram, dateRange)
  };

  // تجميع المقاييس
  const totals = {
    impressions: sum(analytics, 'impressions'),
    engagement: sum(analytics, 'engagement'),
    clicks: sum(analytics, 'clicks'),
    shares: sum(analytics, 'shares'),
    comments: sum(analytics, 'comments'),
    newFollowers: sum(analytics, 'newFollowers')
  };

  return { analytics, totals };
};
Enter fullscreen mode Exit fullscreen mode

أمثلة لجلب التحليلات لمنصات رئيسية

// رؤى فيسبوك
const getFacebookAnalytics = async (pageId, dateRange) => {
  const token = await getFacebookPageToken(pageId);

  const metrics = [
    'page_impressions_unique',
    'page_engaged_users',
    'page_post_engagements',
    'page_clicks',
    'page_fan_adds'
  ];

  const params = new URLSearchParams({
    metric: metrics.join(','),
    since: dateRange.from,
    until: dateRange.until,
    access_token: token
  });

  const response = await fetch(
    `https://graph.facebook.com/v18.0/${pageId}/insights?${params.toString()}`
  );

  return response.json();
};

// تحليلات تويتر
const getTwitterAnalytics = async (userId, dateRange) => {
  const token = await getTwitterToken();

  const response = await fetch(
    `https://api.twitter.com/2/users/${userId}/metrics/private`,
    {
      headers: { 'Authorization': `Bearer ${token}` }
    }
  );

  return response.json();
};

// تحليلات لينكد إن
const getLinkedInAnalytics = async (organizationId, dateRange) => {
  const token = await getLinkedInToken();

  const response = await fetch(
    `https://api.linkedin.com/v2/organizationalEntityFollowerStatistics?q=organizationalEntity&organizationalEntity=${organizationId}`,
    {
      headers: { 'Authorization': `Bearer ${token}` }
    }
  );

  return response.json();
};

// رؤى انستغرام
const getInstagramAnalytics = async (igAccountId, dateRange) => {
  const token = await getInstagramToken();

  const metrics = [
    'impressions',
    'reach',
    'engagement',
    'profile_views',
    'follower_count'
  ];

  const params = new URLSearchParams({
    metric: metrics.join(','),
    period: 'day',
    since: dateRange.from,
    until: dateRange.until
  });

  const response = await fetch(
    `https://graph.facebook.com/v18.0/${igAccountId}/insights?${params.toString()}`,
    {
      headers: { 'Authorization': `Bearer ${token}` }
    }
  );

  return response.json();
};

function sum(analytics, metric) {
  return Object.values(analytics).reduce((total, platform) => {
    return total + (platform.data?.[metric] || 0);
  }, 0);
}
Enter fullscreen mode Exit fullscreen mode

إدارة الفريق

التحكم في الوصول المستند إلى الأدوار

استخدم نموذج أدوار صارم للصلاحيات:

const TEAM_ROLES = {
  ADMIN: 'admin',
  MANAGER: 'manager',
  CONTRIBUTOR: 'contributor',
  VIEWER: 'viewer'
};

const ROLE_PERMISSIONS = {
  [TEAM_ROLES.ADMIN]: ['create', 'read', 'update', 'delete', 'manage_team', 'billing'],
  [TEAM_ROLES.MANAGER]: ['create', 'read', 'update', 'approve_posts'],
  [TEAM_ROLES.CONTRIBUTOR]: ['create', 'read'],
  [TEAM_ROLES.VIEWER]: ['read']
};

const checkPermission = (userRole, requiredPermission) => {
  const permissions = ROLE_PERMISSIONS[userRole] || [];
  return permissions.includes(requiredPermission);
};
Enter fullscreen mode Exit fullscreen mode

تحديد المعدل

حدود المعدل للمنصات

المنصة الحد الأقصى النافذة الزمنية
فيسبوك جراف 200 مكالمة في الساعة لكل مستخدم
تويتر API v2 300 تغريدة لكل 15 دقيقة
لينكدإن 100-500 مكالمة في اليوم
انستغرام 200 مكالمة في الساعة

تطبيق معالجة حدود المعدل

استخدم محدد معدل لكل منصة:

class SocialMediaRateLimiter {
  constructor() {
    this.limits = {
      facebook: { limit: 200, window: 3600000 },
      twitter: { limit: 300, window: 900000 },
      linkedin: { limit: 500, window: 86400000 },
      instagram: { limit: 200, window: 3600000 }
    };
    this.counters = {};
  }

  async request(platform, endpoint, options) {
    await this.waitForCapacity(platform);

    const response = await fetch(endpoint, options);
    this.incrementCounter(platform);

    return response;
  }

  async waitForCapacity(platform) {
    const limit = this.limits[platform];
    const counter = this.counters[platform] || { count: 0, resetTime: Date.now() };

    if (Date.now() > counter.resetTime + limit.window) {
      counter.count = 0;
      counter.resetTime = Date.now();
    }

    if (counter.count >= limit.limit) {
      const waitTime = counter.resetTime + limit.window - Date.now();
      await new Promise(resolve => setTimeout(resolve, waitTime));
    }

    this.counters[platform] = counter;
  }

  incrementCounter(platform) {
    if (!this.counters[platform]) {
      this.counters[platform] = { count: 0, resetTime: Date.now() };
    }
    this.counters[platform].count++;
  }
}
Enter fullscreen mode Exit fullscreen mode

قائمة التحقق من النشر للإنتاج

قبل الإطلاق الفعلي، تحقق من التالي:

  • [ ] تطبيق OAuth 2.0 لجميع المنصات
  • [ ] تخزين الرموز المميزة (tokens) بأمان مع التشفير
  • [ ] إعداد تحديث تلقائي للرموز المميزة
  • [ ] تطبيق تحديد المعدل لكل منصة
  • [ ] إضافة معالجة شاملة للأخطاء
  • [ ] إعداد تسجيل جميع استدعاءات واجهة برمجة التطبيقات (API calls)
  • [ ] إنشاء سير عمل للموافقة على المنشورات
  • [ ] تطبيق الإشراف على المحتوى
  • [ ] إعداد تجميع التحليلات
  • [ ] إنشاء آليات نشر احتياطية

حالات الاستخدام في العالم الحقيقي

لوحة تحكم لوسائل التواصل الاجتماعي

  • التحدي: إدارة 50+ حساب عميل عبر عدة منصات
  • الحل: لوحة تحكم مركزية تدعم النشر متعدد المنصات
  • النتيجة: توفير 60% من الوقت، وحضور متسق للعلامة التجارية

توزيع المحتوى الآلي

  • التحدي: المشاركة اليدوية لمحتوى جديد
  • الحل: أتمتة نشر المقالات الجديدة على المنصات
  • النتيجة: توزيع فوري وزيادة حركة المرور الاجتماعية 3 أضعاف

الخاتمة

رغم إيقاف Hootsuite للواجهة العامة، تمنحك واجهات برمجة التطبيقات الأصلية إمكانيات متقدمة لإدارة وسائل التواصل الاجتماعي. النقاط الأساسية:

  • تطبيق OAuth 2.0 لكل منصة
  • لكل منصة حدود معدل مختلفة يجب احترامها
  • النشر الموحد يتطلب منطق خاص لكل منصة
  • تجميع التحليلات يمنحك رؤى متعددة المنصات
  • Apidog يبسط اختبار API والتعاون بين الفرق

قسم الأسئلة الشائعة

هل ما زالت Hootsuite تمتلك واجهة برمجة تطبيقات (API)؟

لا، أوقفت Hootsuite دعم API العامة عام 2024. استخدم واجهات برمجة تطبيقات كل منصة أو أدوات مثل Buffer، Sprout Social، Agorapulse.

كيف يمكنني النشر على عدة منصات في وقت واحد؟

عليك تطبيق OAuth لكل منصة، ثم بناء دالة نشر موحدة تستدعي API كل منصة بشكل متوازي.

ما هي حدود المعدل لواجهات برمجة تطبيقات وسائل التواصل الاجتماعي؟

تختلف الحدود حسب المنصة: فيسبوك (200/ساعة)، تويتر (300/15 دقيقة)، لينكدإن (100-500/يوم)، انستغرام (200/ساعة).

كيف أقوم بجدولة المنشورات؟

خزن المنشورات في قاعدة بيانات مع وقت مجدول (scheduled_time) ثم استخدم قائمة انتظار مهام (Bull، Agenda) للنشر تلقائيًا في الوقت المحدد.

هل يمكنني الحصول على تحليلات من جميع المنصات؟

نعم، كل منصة توفر API للتحليلات. قم بجمع البيانات لإنشاء تقارير متعددة المنصات.

Top comments (0)