A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://developers.notion.com/page/log-strava-activity-in-notion below:

Log Strava Activity in Notion

Log Strava Activity in Notion

This developer documentation provides a step-by-step guide to create an integration between the Notion API and the Strava API using JavaScript. The integration fetches data from a Strava athlete's activities and populates a Notion database with their activity data.

πŸ”‘

This integration requires following Strava's OAuth flow. Please refer to Strava's OAuth documentation for more information.

Strava API Key

  1. Log in to your Strava account.
  2. Go to Strava API.
  3. Click on Create An App.
  4. Fill in the required details and click Create.
  5. Copy the Client ID and Client Secret.

Notion API Key

  1. Log in to your Notion account.
  2. Go to Notion Integrations.
  3. Click on New Integration.
  4. Fill in the required details and click Submit.
  5. Copy the generated Internal Integration Token.
  1. Create a new database in Notion with the following properties:
  1. Share the database with your integration:

This step is not necessary but we suggest projects to be structured like so:

project-root/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ config/
β”‚   β”‚   └── spotify.js
β”‚   β”‚   └── notion.js
β”‚   β”œβ”€β”€ integrations/
β”‚   β”‚   β”œβ”€β”€ spotifyIntegration.js
β”‚   β”‚   └── notionIntegration.js
β”‚   β”œβ”€β”€ main.js
β”‚   β”œβ”€β”€ server.js
β”œβ”€β”€ .env
β”œβ”€β”€ package.json

Create a .env file in your project directory with the following with the following information:

NOTION_TOKEN='your_notion_integration_token'
NOTION_DATABASE_ID='your_notion_database_id'
STRAVA_CLIENT_ID='your_strava_client_id'
STRAVA_CLIENT_SECRET='your_strava_client_secret'
STRAVA_ACCESS_TOKEN='your_strava_access_token'
STRAVA_REFRESH_TOKEN='your_strava_refresh_token'
🚨

Please note that you will have to update your .env file with your STRAVA_ACCESS_TOKEN and STRAVA_REFRESH_TOKEN after completing Strava’s OAuth flow.

Install the required Node.js packages using the following command:

npm install @notionhq/client dotenv express https

Additionally, create a package.json file and add the following:

{
    "name": "strava_integration",
    "version": "1.0.0",
    "main": "src/main.js",
    "scripts": {
        "start": "node src/main.js"
    },
    "dependencies": {
        "@notionhq/client": "^1.0.4",
        "dotenv": "^8.6.0",
        "express": "^4.19.2",
        "https": "^1.0.0"
    }
}

Create server.js to handle the OAuth flow:

const express = require('express');
const https = require('https');
const querystring = require('querystring');
require('./utils/dotenv');

const app = express();
const PORT = 3000;

app.get('/', (req, res) => {
  res.send('<h1>Strava OAuth Integration</h1><p><a href="/auth">Click here to authorize with Strava</a></p>');
});

app.get('/auth', (req, res) => {
  const authUrl = `https://www.strava.com/oauth/authorize?client_id=${process.env.STRAVA_CLIENT_ID}&response_type=code&redirect_uri=http://localhost:${PORT}/exchange_token&approval_prompt=force&scope=activity:read_all`;
  res.redirect(authUrl);
});

app.get('/exchange_token', (req, res) => {
  const { code } = req.query;

  const postData = querystring.stringify({
    client_id: process.env.STRAVA_CLIENT_ID,
    client_secret: process.env.STRAVA_CLIENT_SECRET,
    code: code,
    grant_type: 'authorization_code'
  });

  const options = {
    hostname: 'www.strava.com',
    path: '/oauth/token',
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    }
  };

  const request = https.request(options, (response) => {
    let data = '';

    response.on('data', (chunk) => {
      data += chunk;
    });

    response.on('end', () => {
      const parsedData = JSON.parse(data);
      if (parsedData.errors) {
        res.status(400).send(`Error: ${parsedData.message}`);
      } else {
        res.send(`Access Token: ${parsedData.access_token}<br>Refresh Token: ${parsedData.refresh_token}`);
      }
    });
  });

  request.on('error', (e) => {
    res.status(500).send(`Error: ${e.message}`);
  });

  request.write(postData);
  request.end();
});

app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});

Create strava.js to set up the Strava API client:

const https = require('https');
const querystring = require('querystring');

// Function to get Strava access token
async function getStravaAccessToken() {
  const postData = querystring.stringify({
    client_id: process.env.STRAVA_CLIENT_ID,
    client_secret: process.env.STRAVA_CLIENT_SECRET,
    refresh_token: process.env.STRAVA_REFRESH_TOKEN,
    grant_type: 'refresh_token'
  });

  const options = {
    hostname: 'www.strava.com',
    path: '/oauth/token',
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    }
  };

  return new Promise((resolve, reject) => {
    const req = https.request(options, (res) => {
      let data = '';

      res.on('data', (chunk) => {
        data += chunk;
      });

      res.on('end', () => {
        const parsedData = JSON.parse(data);
        if (parsedData.errors) {
          reject(new Error(`Error fetching access token: ${parsedData.message}`));
        } else {
          resolve(parsedData.access_token);
        }
      });
    });

    req.on('error', (e) => {
      reject(e);
    });

    req.write(postData);
    req.end();
  });
}

module.exports = { getStravaAccessToken };

Create a notion.js file to set up the Notion API client using the @notionhq/client library. Use your Notion integration token and database ID.

// notion.js
const { Client } = require('@notionhq/client');
const dotenv = require('dotenv');

dotenv.config();

const notion = new Client({ auth: process.env.NOTION_TOKEN });
const databaseId = process.env.NOTION_DATABASE_ID;

module.exports = { notion, databaseId };

Create a stravaIntegration.js file to fetch activity data from your Strava account:

const https = require('https');
const { getStravaAccessToken } = require('../config/strava');

// Helper function to make GET requests
async function fetchJson(url, headers) {
  return new Promise((resolve, reject) => {
    const options = {
      headers: headers
    };

    https.get(url, options, (res) => {
      let data = '';

      res.on('data', (chunk) => {
        data += chunk;
      });

      res.on('end', () => {
        resolve(JSON.parse(data));
      });
    }).on('error', (e) => {
      reject(e);
    });
  });
}

// Convert pace from min/km to min/mile
function convertPaceToMinPerMile(paceInMinPerKm) {
  const minPerMile = paceInMinPerKm * 1.60934;
  const minutes = Math.floor(minPerMile);
  const seconds = Math.round((minPerMile - minutes) * 60);
  return `${minutes}:${seconds < 10 ? '0' : ''}${seconds} min/mile`;
}

// Convert distance from meters to miles
function convertMetersToMiles(meters) {
  return meters * 0.000621371;
}

// Fetch activities from Strava
async function getStravaActivities() {
  const accessToken = await getStravaAccessToken();
  const headers = {
    'Authorization': `Bearer ${accessToken}`
  };

  const activitiesResponse = await fetchJson('https://www.strava.com/api/v3/athlete/activities', headers);

  // Log the response to understand its structure
  console.log('Activities Response:', activitiesResponse);

  if (!Array.isArray(activitiesResponse)) {
    throw new Error('Invalid response from Strava API');
  }

  return activitiesResponse.map(activity => {
    const paceInMinPerKm = (activity.moving_time / 60) / (activity.distance / 1000);
    const paceInMinPerMile = convertPaceToMinPerMile(paceInMinPerKm);
    const distanceInMiles = convertMetersToMiles(activity.distance);

    return {
      name: activity.name,
      distance: distanceInMiles,
      pace: paceInMinPerMile,
      duration: new Date(activity.moving_time * 1000).toISOString().substr(11, 8), // Duration in HH:MM:SS
      elevation_gain: activity.total_elevation_gain,
      type: activity.type,
      date: activity.start_date,
      calories: activity.calories
    };
  });
}

module.exports = { getStravaActivities };

Create a notionIntegration.js file to handle populating the Notion database with all Strava activities.

const { Client } = require('@notionhq/client');

// Initialize the Notion client
const notion = new Client({ auth: process.env.NOTION_TOKEN});

// Add data to the Notion database
async function addToNotionDatabase(databaseId, activity) {
  try {
    await notion.pages.create({
      parent: { database_id: databaseId },
      properties: {
        'Name': {
          title: [
            {
              text: {
                content: activity.name
              }
            }
          ]
        },
        'Distance': {
          number: activity.distance
        },
        'Pace': {
          rich_text: [
            {
              text: {
                content: activity.pace
              }
            }
          ]
        },
        'Duration': {
          rich_text: [
            {
              text: {
                content: activity.duration
              }
            }
          ]
        },
        'Elevation Gain': {
          number: activity.elevation_gain
        },
        'Type': {
          rich_text: [
            {
              text: {
                content: activity.type
              }
            }
          ]
        },
        'Date': {
          date: {
            start: activity.date
          }
        },
        'Calories': {
          number: activity.calories || 0 // Default to 0 if undefined
        }
      }
    });
  } catch (error) {
    console.error('Error adding to Notion database:', error);
  }
}

module.exports = { addToNotionDatabase };

Createa main.js file that uses the modules created above to execute the integration logic.

require('dotenv').config();

const { getStravaActivities } = require('./integrations/stravaIntegration');
const { addToNotionDatabase } = require('./integrations/notionIntegration');

const NOTION_DATABASE_ID = process.env.NOTION_DATABASE_ID;

// Main function to fill the Notion database with Strava activities
async function fillNotionDatabase() {
  try {
    const activities = await getStravaActivities();
    
    for (const activity of activities) {
      await addToNotionDatabase(NOTION_DATABASE_ID, activity);
      console.log(`Added to Notion: Name: ${activity.name}, Distance: ${activity.distance}, Pace: ${activity.pace}`);
    }
  } catch (error) {
    console.error('Error filling Notion database:', error);
  }
}

fillNotionDatabase();
  1. Start the OAuth Server:
  1. Open your browser and navigate to http://localhost:3000:
  2. Click the link to authorize with Strava:
  3. Authorize the application:
  4. The server will exchange the authorization code for an access token and refresh token:
  5. Copy the refresh token and update your .env file with it.

Execute the integration script by running the following command:

πŸ”‘

Customize the code according to your Notion database structure and the properties you want to include for each Strava activity.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4