Skip to main content

How would you guys recommend I try to identify runs that are workouts from the SummaryActivity object?

For context: I have a group of athletes who've authenticated my app whose activities I poll to a Google Sheet via the Google App Script and I want to be able to identify their workouts.

I have a few options in my head:

1. Ask that my athletes mark their workouts as workouts in Strava, from which I should be able to grab the workout_type and use that (?). I still can't find any place which shows what the valid workout types are. Risk assuming this is even valid: They could forget to mark their run as a workout and then that activity gets overlooked.

2. Try to use the laps data. Assumptions: All athletes will use lapping for their workouts and never use lapping for their easy runs. Womp womp.

3. Try for a combination of the above two fields: workout_type and laps. From this make a decision on if it's a workout or not. If they forget to mark a workout type, check laps and see if there are fast laps much faster than their easy run pace (or something like that). If laps look all slow / there's only one, mark it as an easy run.

4. Cry. Strava API has too many limitations. Forget about my dreams and call it a wrap.

Hint: This is me begging for you Strava API developers to enhance the API to address its limitations such as this. 🙂 Any help would be appreciated.

The workout_type is a bit undocumented. I can only say from experience that for outdoor runs the workout_type is always 3 if the user has tagged the run as a workout.


I think your best bet is to ask the athletes to mark workouts in Strava and use that field.

I don't know that there's a reliable way to automatically detect a workout since every workout will look different. On top of that, not everyone uses their devices the same way so they may not be using the lap button for every interval, may not be loading a workout onto their device (and instead just monitor time), or whatever other variations you can think of. Some devices have auto-lap enabled for time or distance, so looking at laps may falsely indicate a workout. I suppose you could look at variation across laps and try to see if some are significantly harder/easier than others and detect it that way? Also if you have history for these athletes and know their normal pace you could combine that to make a more accurate guess

As for the workout_type field, while it isn't documented you can figure out the meanings by modifying an activity multiple times and reading it back to see how the field changes. To save you the trouble, here's the table I came up with. Note that run and ride have different values (generally ride has run value+  10 except for 'workout'). Also keep in mind that since it isn't documented Strava could change it at any time.

 

 

'workout_type' : {
'run' : {
'0' : 'None',
'1' : 'Race',
'3' : 'Workout',
'2' : 'Long Run'
}
'ride' : {
'10' : 'None',
'11' : 'Race',
'12' : 'Workout'
}
}

 

 

 


Yeah, I think I'll bank on them marking their runs as workouts, and maybe use lap variance (with their average pace for the week) as a backup determinant. Thanks for the mapping of workout types by the way!


If your users are mainly using Garmin or Wahoo devices to record their activities and run workouts, I'll throw in a self-plug for my app @ https://activityfix.com. One of the available comparisons (and updates) that can be done is on the fit file name provided by Garmin/Wahoo. If they had a workout loaded while recording, the fit file name is set to the name of the workout. You could have them set up a rule to automatically change the workout type based on that data (or add that information into the title/description/private notes of their activity) so it is available to your app. If you're using webhooks you'd need to delay your processing until those changes were made but that's pretty straight forward and would need to be done anyway if you're relying on them to manually set workout type, since changing that field doesn't generate a webhook call.


Here is my PHP enum for the workout type:

enum WorkoutType: int
{
case Run_None = 0;
case Run_Race = 1;
case Run_Long_Run = 2;
case Run_Workout = 3;
case Ride_None = 10;
case Ride_Race = 11;
case Ride_Workout = 12;
}

 


Reply