> ## Documentation Index
> Fetch the complete documentation index at: https://developers.notion.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Log Strava Activity in Notion

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

export const developerConnectionsUrl = "https://app.notion.com/developers/connections";

<Warning>
  This connection requires following Strava's OAuth flow. Please refer to [Strava's OAuth documentation](https://developers.strava.com/docs/authentication/) for more information.
</Warning>

## Prerequisites

* Node.js installed on your machine
* A Strava Developer account
* A Notion account

## Step 1 - Get Your API Keys

**Strava API Key**

<Steps>
  <Step>
    Log in to your Strava account.
  </Step>

  <Step>
    Go to [Strava API](https://www.strava.com/settings/api).
  </Step>

  <Step>
    Click on **Create An App**.
  </Step>

  <Step>
    Fill in the required details and click **Create**.
  </Step>

  <Step>
    Copy the **Client ID** and **Client Secret**.
  </Step>
</Steps>

**Notion API Key**

<Steps>
  <Step>
    Log in to your Notion account.
  </Step>

  <Step>
    Go to <a href={developerConnectionsUrl}>Notion Connections</a>.
  </Step>

  <Step>
    Click on **New Connection**.
  </Step>

  <Step>
    Fill in the required details and click **Submit**.
  </Step>

  <Step>
    Copy the generated **Installation access token**.
  </Step>
</Steps>

## Step 2 - Set Up Your Notion Database

<Steps>
  <Step>
    Create a new database in Notion with the following properties:

    * **Name** (Title)
    * **Distance** (Number)
    * **Pace** (Text)
    * **Duration** (Text)
    * **Elevation Gain** (Number)
    * **Type** (Text)
    * **Date** (Date)
    * **Calories** (Number)
  </Step>

  <Step>
    Share the database with your connection:

    * Click on the three dots in the top-right corner of the page.
    * Under **Connections**, click on **Connect to** and search for your connection and invite it.
  </Step>
</Steps>

## Step 3 - Project Structure

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

```shell theme={null}
project-root/
├── src/
│   ├── config/
│   │   └── spotify.js
│   │   └── notion.js
│   ├── integrations/
│   │   ├── spotifyIntegration.js
│   │   └── notionIntegration.js
│   ├── main.js
│   ├── server.js
```

## Step 4 - Create .env file

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

```yaml YAML theme={null}
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'
```

<Danger>
  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.
</Danger>

## Step 5 - Packages

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

```shell theme={null}
npm install @notionhq/client dotenv express https
```

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

```json JSON theme={null}
{
    "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"
    }
}
```

## Step 6 - OAuth Flow

Create `server.js` to handle the OAuth flow:

```javascript JavaScript expandable theme={null}
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 Connection</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}`);
});
```

## Step 7 - Set Up Strava API Client

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

```javascript JavaScript expandable theme={null}
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 };
```

## Step 8 - Set Up Notion API Client

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

```javascript JavaScript theme={null}
// 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 };
```

## Step 9 - Fetch Activity Data From Strava

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

```javascript JavaScript expandable theme={null}
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 };
```

## Step 10 - Populate Notion Database with Strava Activity Data

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

```javascript JavaScript expandable theme={null}
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 };
```

## Step 11 - Main Script

Create a `main.js` file that uses the modules created above to execute the connection logic.

```javascript JavaScript expandable theme={null}
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();
```

## Step 12 - Run the OAuth Flow

<Steps>
  <Step>
    Start the OAuth Server:

    ```shell theme={null}
    node src/server.js
    ```
  </Step>

  <Step>
    Open your browser and navigate to `http://localhost:3000`:

    * You should see a page with a link to authorize with Strava.
  </Step>

  <Step>
    Click the link to authorize with Strava:

    * This will redirect you to Strava's authorization page.
  </Step>

  <Step>
    Authorize the application:

    * Strava will redirect you to a page with an authorization code.
  </Step>

  <Step>
    The server will exchange the authorization code for an access token and refresh token:

    * The tokens will be displayed on the page.
  </Step>

  <Step>
    **Copy the refresh token and update your `.env` file with it.**
  </Step>
</Steps>

## Step 13 - Run the Connection

Execute the connection script by running the following command:

```shell theme={null}
npm start
```

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