Skip to content

Latest commit

Β 

History

History
254 lines (224 loc) Β· 7.33 KB

File metadata and controls

254 lines (224 loc) Β· 7.33 KB

Spotify Data Collection & Storage Guide

🎡 What Spotify Data to Collect

Essential Data for Reconnection

interface SpotifyUserData {
  profile: {
    id: string;           // Spotify User ID (unique identifier)
    email: string;        // User's Spotify email
    display_name: string; // User's display name
    country?: string;     // User's country
    product?: string;     // Subscription type (free/premium)
    images?: Array<{ url: string }>; // Profile images
  };
  refreshToken: string;   // For getting new access tokens
  topTracks: Array<{      // User's music preferences
    id: string;
    name: string;
    artists: Array<{ id: string; name: string }>;
    album: { id: string; name: string; images: Array<{ url: string }> };
    popularity: number;
    duration_ms: number;
  }>;
  recentlyPlayed: Array<{ // Recent listening history
    track: SpotifyTopTrack;
    played_at: string;
  }>;
  playlists: Array<{      // User's playlists
    id: string;
    name: string;
    description: string;
    images: Array<{ url: string }>;
    tracks: { total: number };
    owner: { id: string; display_name: string };
  }>;
}

πŸ”’ How to Store Data Securely

Backend Database Schema (Example)

-- Users table
CREATE TABLE users (
  id UUID PRIMARY KEY,
  email VARCHAR(255) UNIQUE NOT NULL,
  invitation_code VARCHAR(255) NOT NULL,
  created_at TIMESTAMP DEFAULT NOW()
);

-- Spotify connections table
CREATE TABLE spotify_connections (
  id UUID PRIMARY KEY,
  user_id UUID REFERENCES users(id),
  spotify_user_id VARCHAR(255) UNIQUE NOT NULL,
  spotify_email VARCHAR(255) NOT NULL,
  display_name VARCHAR(255),
  country VARCHAR(10),
  product VARCHAR(50),
  profile_image_url TEXT,
  refresh_token TEXT NOT NULL, -- ENCRYPT THIS!
  access_token TEXT, -- ENCRYPT THIS!
  token_expires_at TIMESTAMP,
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

-- Music preferences table
CREATE TABLE spotify_music_preferences (
  id UUID PRIMARY KEY,
  spotify_connection_id UUID REFERENCES spotify_connections(id),
  top_tracks JSONB, -- Store as JSON
  recently_played JSONB,
  playlists JSONB,
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

Security Best Practices

  1. Encrypt Sensitive Data: Always encrypt refresh_token and access_token
  2. Use Environment Variables: Store encryption keys securely
  3. Token Rotation: Implement automatic token refresh
  4. Data Retention: Only store what you need
  5. GDPR Compliance: Allow users to delete their data

πŸ”„ How Reconnection Works

1. User Returns to Your App

// Check if user has existing Spotify connection
const existingConnection = await checkExistingSpotifyConnection(userId);

if (existingConnection) {
  // Check if access token is still valid
  if (isTokenValid(existingConnection.access_token)) {
    // Token is valid, user can use the app
    return { connected: true, userData: existingConnection };
  } else {
    // Token expired, refresh it
    const newTokens = await refreshSpotifyToken(existingConnection.refresh_token);
    await updateUserTokens(userId, newTokens);
    return { connected: true, userData: existingConnection };
  }
} else {
  // No existing connection, user needs to connect again
  return { connected: false };
}

2. Token Refresh Process

async function refreshSpotifyToken(refreshToken: string) {
  const response = await fetch('https://accounts.spotify.com/api/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      'Authorization': `Basic ${Buffer.from(
        `${process.env.SPOTIFY_CLIENT_ID}:${process.env.SPOTIFY_CLIENT_SECRET}`
      ).toString('base64')}`
    },
    body: new URLSearchParams({
      grant_type: 'refresh_token',
      refresh_token: refreshToken
    })
  });

  const data = await response.json();
  return {
    access_token: data.access_token,
    expires_in: data.expires_in,
    refresh_token: data.refresh_token || refreshToken // Keep old one if not provided
  };
}

πŸ“Š Data Usage Examples

1. Personalized Recommendations

// Use top tracks and recently played for recommendations
const userPreferences = {
  favoriteGenres: extractGenresFromTracks(userData.topTracks),
  favoriteArtists: extractArtistsFromTracks(userData.topTracks),
  listeningPatterns: analyzeListeningHistory(userData.recentlyPlayed)
};

2. Social Features

// Show user's music taste
const userMusicProfile = {
  displayName: userData.profile.display_name,
  topTracks: userData.topTracks.slice(0, 5),
  favoritePlaylists: userData.playlists.slice(0, 3),
  listeningStats: {
    totalTracks: userData.topTracks.length,
    totalPlaylists: userData.playlists.length
  }
};

3. Rewards & Gamification

// Track user engagement
const userEngagement = {
  tracksListened: userData.recentlyPlayed.length,
  playlistsCreated: userData.playlists.filter(p => p.owner.id === userData.profile.id).length,
  premiumUser: userData.profile.product === 'premium'
};

πŸš€ Implementation Steps

1. Update Your Backend API

Create a new endpoint for comprehensive data:

// POST /api/v1/auth/spotify-connect-comprehensive
{
  spotifyEmail: string;
  invitationCode: string;
  spotifyData: SpotifyUserData;
}

2. Add Token Refresh Logic

// Middleware to check and refresh tokens
async function ensureValidSpotifyToken(userId: string) {
  const connection = await getSpotifyConnection(userId);
  
  if (!connection) {
    throw new Error('No Spotify connection found');
  }
  
  if (isTokenExpired(connection.token_expires_at)) {
    const newTokens = await refreshSpotifyToken(connection.refresh_token);
    await updateSpotifyTokens(userId, newTokens);
    return newTokens.access_token;
  }
  
  return connection.access_token;
}

3. Add Reconnection UI

// In your app, check connection status
const { spotifyUser, spotifyUserData } = useSpotifyAuth();

if (spotifyUser && spotifyUserData) {
  // User is connected, show their data
  return <UserDashboard userData={spotifyUserData} />;
} else {
  // User needs to connect
  return <SpotifyConnectButton />;
}

πŸ” Monitoring & Analytics

Track These Metrics

  • Connection Success Rate: How often users successfully connect
  • Token Refresh Success Rate: How often token refresh works
  • Data Collection Completeness: How much data you're getting per user
  • User Engagement: How users interact with their Spotify data

Error Handling

// Handle common Spotify API errors
try {
  const userData = await getSpotifyUserData(accessToken);
} catch (error) {
  if (error.status === 401) {
    // Token expired, refresh it
    await refreshUserToken(userId);
  } else if (error.status === 403) {
    // User revoked access, remove connection
    await removeSpotifyConnection(userId);
  }
}

πŸ“ Next Steps

  1. Implement the comprehensive data collection (already done in frontend)
  2. Create the backend API endpoint for storing comprehensive data
  3. Add token refresh logic to your backend
  4. Implement reconnection flow in your app
  5. Add data encryption for sensitive tokens
  6. Test the complete flow with real users

This setup will give you everything you need to provide a seamless Spotify experience for your users! πŸŽ‰