Skip to main content

Overview

The Bouncy.ai API provides detailed analytics for individual links and aggregate data across your entire account. Track:
  • Click counts - Total clicks and unique visitors
  • Geographic data - Country and city-level location
  • Device information - Mobile vs desktop, OS, browser
  • Referrer sources - Where your traffic comes from
  • Time series data - Clicks over time with hourly/daily granularity
Retrieve detailed analytics for a specific link:
curl https://api.bouncy.ai/v1/analytics/links/link_abc123 \
  -H "X-Api-Key: bcy_live_pk_YOUR_API_KEY"

Response

{
  "linkId": "link_abc123",
  "shortUrl": "https://bouncy.link/summer",
  "totalClicks": 1234,
  "uniqueVisitors": 892,
  "lastClickAt": "2026-02-06T11:30:00Z",
  "topCountries": [
    { "country": "US", "clicks": 456 },
    { "country": "GB", "clicks": 234 },
    { "country": "CA", "clicks": 123 }
  ],
  "topCities": [
    { "city": "London", "country": "GB", "clicks": 89 },
    { "city": "New York", "country": "US", "clicks": 67 }
  ],
  "topReferrers": [
    { "referrer": "twitter.com", "clicks": 345 },
    { "referrer": "facebook.com", "clicks": 234 },
    { "referrer": "direct", "clicks": 189 }
  ],
  "devices": {
    "mobile": 678,
    "desktop": 456,
    "tablet": 100
  },
  "browsers": {
    "Chrome": 567,
    "Safari": 345,
    "Firefox": 234,
    "Edge": 88
  },
  "operatingSystems": {
    "iOS": 456,
    "Android": 345,
    "Windows": 234,
    "macOS": 199
  }
}

Filter Analytics by Date Range

Add query parameters to filter by date:
GET /v1/analytics/links/link_abc123?startDate=2026-01-01&endDate=2026-01-31
curl "https://api.bouncy.ai/v1/analytics/links/link_abc123?startDate=2026-01-01&endDate=2026-01-31" \
  -H "X-Api-Key: bcy_live_pk_YOUR_API_KEY"

Get Summary Analytics

Get aggregated analytics across all your links:
curl https://api.bouncy.ai/v1/analytics/summary \
  -H "X-Api-Key: bcy_live_pk_YOUR_API_KEY"

Response

{
  "totalLinks": 245,
  "totalClicks": 45678,
  "uniqueVisitors": 32456,
  "averageClicksPerLink": 186,
  "topLinks": [
    {
      "linkId": "link_abc123",
      "shortUrl": "https://bouncy.link/summer",
      "clicks": 2345
    },
    {
      "linkId": "link_def456",
      "shortUrl": "https://bouncy.link/promo",
      "clicks": 1987
    }
  ],
  "topCountries": [
    { "country": "US", "clicks": 15678 },
    { "country": "GB", "clicks": 8765 },
    { "country": "CA", "clicks": 5432 }
  ],
  "clicksOverTime": [
    { "date": "2026-02-01", "clicks": 234 },
    { "date": "2026-02-02", "clicks": 345 },
    { "date": "2026-02-03", "clicks": 456 }
  ]
}

Filter Summary by Tags

Get analytics for links with a specific tag:
GET /v1/analytics/summary?tag=summer2026
const response = await fetch(
  'https://api.bouncy.ai/v1/analytics/summary?tag=summer2026',
  {
    headers: { 'X-Api-Key': 'bcy_live_pk_YOUR_API_KEY' }
  }
);

const campaignAnalytics = await response.json();
console.log(`Campaign clicks: ${campaignAnalytics.totalClicks}`);
This is perfect for tracking campaign performance!

Real-World Use Cases

Campaign Performance Dashboard

Build a custom dashboard showing performance across campaigns:
async function getCampaignStats(campaignTag) {
  const response = await fetch(
    `https://api.bouncy.ai/v1/analytics/summary?tag=${campaignTag}`,
    {
      headers: { 'X-Api-Key': 'bcy_live_pk_YOUR_API_KEY' }
    }
  );

  const stats = await response.json();

  return {
    campaign: campaignTag,
    totalClicks: stats.totalClicks,
    uniqueVisitors: stats.uniqueVisitors,
    topLink: stats.topLinks[0],
    topCountry: stats.topCountries[0]
  };
}

const campaigns = ['summer2026', 'winter2026', 'blackfriday'];
const results = await Promise.all(
  campaigns.map(tag => getCampaignStats(tag))
);

console.table(results);

Automated Reporting

Send weekly email reports with link performance:
import nodemailer from 'nodemailer';

async function sendWeeklyReport() {
  // Get last 7 days of data
  const endDate = new Date().toISOString().split('T')[0];
  const startDate = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
    .toISOString()
    .split('T')[0];

  const response = await fetch(
    `https://api.bouncy.ai/v1/analytics/summary?startDate=${startDate}&endDate=${endDate}`,
    {
      headers: { 'X-Api-Key': 'bcy_live_pk_YOUR_API_KEY' }
    }
  );

  const stats = await response.json();

  const emailBody = `
    Weekly Link Report (${startDate} to ${endDate})

    Total Clicks: ${stats.totalClicks}
    Unique Visitors: ${stats.uniqueVisitors}

    Top Performing Links:
    ${stats.topLinks.map(link => `  - ${link.shortUrl}: ${link.clicks} clicks`).join('\n')}

    Top Countries:
    ${stats.topCountries.map(c => `  - ${c.country}: ${c.clicks} clicks`).join('\n')}
  `;

  // Send email (configure your SMTP settings)
  const transporter = nodemailer.createTransport({...});
  await transporter.sendMail({
    to: '[email protected]',
    subject: 'Weekly Bouncy.ai Link Report',
    text: emailBody
  });
}

// Run weekly
setInterval(sendWeeklyReport, 7 * 24 * 60 * 60 * 1000);

A/B Testing

Compare performance of different link variations:
async function compareLinks(linkIds) {
  const results = await Promise.all(
    linkIds.map(async (linkId) => {
      const response = await fetch(
        `https://api.bouncy.ai/v1/analytics/links/${linkId}`,
        {
          headers: { 'X-Api-Key': 'bcy_live_pk_YOUR_API_KEY' }
        }
      );
      return response.json();
    })
  );

  // Calculate conversion rates (assuming you track conversions)
  const comparison = results.map(analytics => ({
    url: analytics.shortUrl,
    clicks: analytics.totalClicks,
    uniqueVisitors: analytics.uniqueVisitors,
    clickThroughRate: (analytics.uniqueVisitors / analytics.totalClicks * 100).toFixed(2) + '%'
  }));

  console.table(comparison);

  // Determine winner
  const winner = comparison.reduce((prev, current) =>
    current.clicks > prev.clicks ? current : prev
  );

  console.log(`Winner: ${winner.url} with ${winner.clicks} clicks`);
  return winner;
}

const testLinks = ['link_abc123', 'link_def456', 'link_ghi789'];
const winner = await compareLinks(testLinks);

Analytics Best Practices

Analytics don’t change instantly - cache results for a few minutes:
const cache = new Map();
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes

async function getCachedAnalytics(linkId) {
  const cached = cache.get(linkId);

  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.data;
  }

  const response = await fetch(
    `https://api.bouncy.ai/v1/analytics/links/${linkId}`,
    {
      headers: { 'X-Api-Key': 'bcy_live_pk_YOUR_API_KEY' }
    }
  );

  const data = await response.json();
  cache.set(linkId, { data, timestamp: Date.now() });

  return data;
}
When querying large date ranges, the API processes more data. For better performance, query smaller date ranges:
// ❌ Slow: Query entire year
const yearAnalytics = await fetch(
  'https://api.bouncy.ai/v1/analytics/summary?startDate=2026-01-01&endDate=2026-12-31'
);

// ✅ Fast: Query last 30 days
const monthAnalytics = await fetch(
  'https://api.bouncy.ai/v1/analytics/summary?startDate=2026-01-07&endDate=2026-02-06'
);
Always tag your links by campaign so you can filter analytics later:
// Create link with campaign tags
await fetch('https://api.bouncy.ai/v1/links', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'bcy_live_pk_YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    url: 'https://example.com/sale',
    tags: ['summer2026', 'instagram', 'story']
  })
});

// Later: Get campaign analytics
const analytics = await fetch(
  'https://api.bouncy.ai/v1/analytics/summary?tag=summer2026'
);

Next Steps