{"id":146874,"date":"2021-09-17T21:05:06","date_gmt":"2021-09-17T21:05:06","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/strava-activities-nmr\/"},"modified":"2026-03-19T22:47:40","modified_gmt":"2026-03-19T22:47:40","slug":"nmr-strava-activities","status":"publish","type":"plugin","link":"https:\/\/twd.wordpress.org\/plugins\/nmr-strava-activities\/","author":17805734,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_crdt_document":"","version":"1.0.12","stable_tag":"1.0.12","tested":"6.8.5","requires":"5.2","requires_php":"","requires_plugins":null,"header_name":"NMR Strava activities","header_author":"Mircea N.","header_description":"Get a copy of Strava activities (webhook) as they are recorded in Strava. You must setup a Strava API Application. Users must allow your Strava application to access (read) their data.","assets_banners_color":"f6f6f9","last_updated":"2026-03-19 22:47:40","external_support_url":"","external_repository_url":"","donate_link":"https:\/\/paypal.me\/mirceatm","header_plugin_uri":"https:\/\/namir.ro\/strava-activities\/","header_author_uri":"","rating":0,"author_block_rating":0,"active_installs":100,"downloads":3055,"num_ratings":1,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.1":{"tag":"1.0.1","author":"mirceatm","date":"2022-02-02 20:42:22"},"1.0.10":{"tag":"1.0.10","author":"mirceatm","date":"2025-01-13 13:35:27"},"1.0.11":{"tag":"1.0.11","author":"mirceatm","date":"2025-03-10 23:34:47"},"1.0.12":{"tag":"1.0.12","author":"mirceatm","date":"2026-03-19 22:47:40"},"1.0.2":{"tag":"1.0.2","author":"mirceatm","date":"2022-02-04 23:52:53"},"1.0.3":{"tag":"1.0.3","author":"mirceatm","date":"2022-03-18 19:54:30"},"1.0.4":{"tag":"1.0.4","author":"mirceatm","date":"2022-10-30 10:31:51"},"1.0.5":{"tag":"1.0.5","author":"mirceatm","date":"2023-01-21 14:45:43"},"1.0.6":{"tag":"1.0.6","author":"mirceatm","date":"2023-10-10 20:11:14"},"1.0.7":{"tag":"1.0.7","author":"mirceatm","date":"2024-12-20 17:48:34"},"1.0.8":{"tag":"1.0.8","author":"mirceatm","date":"2024-12-20 19:46:08"},"1.0.9":{"tag":"1.0.9","author":"mirceatm","date":"2024-12-20 22:51:19"}},"upgrade_notice":[],"ratings":{"1":0,"2":0,"3":0,"4":0,"5":0},"assets_icons":{"icon-128x128.jpg":{"filename":"icon-128x128.jpg","revision":2600854,"resolution":"128x128","location":"assets","locale":""},"icon-256x256.jpg":{"filename":"icon-256x256.jpg","revision":2600854,"resolution":"256x256","location":"assets","locale":""}},"assets_banners":{"banner-772x250.jpg":{"filename":"banner-772x250.jpg","revision":2600854,"resolution":"772x250","location":"assets","locale":""}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.1","1.0.10","1.0.11","1.0.12","1.0.2","1.0.3","1.0.4","1.0.5","1.0.6","1.0.7","1.0.8","1.0.9"],"block_files":[],"assets_screenshots":{"screenshot-1.jpg":{"filename":"screenshot-1.jpg","revision":2600854,"resolution":"1","location":"assets","locale":""},"screenshot-2.jpg":{"filename":"screenshot-2.jpg","revision":2600854,"resolution":"2","location":"assets","locale":""}},"screenshots":{"1":"Placeholder: Settings \u2192 Strava NMR (replace with a real screenshot in the WordPress.org <code>assets<\/code> folder when publishing).","2":"Placeholder: Example of activity data \/ <code>[strava_nmr_table]<\/code> output (replace with a real screenshot on WordPress.org)."},"jetpack_post_was_ever_published":false},"plugin_section":[],"plugin_tags":[14615,6165,87,22202,34953],"plugin_category":[59],"plugin_contributors":[182471],"plugin_business_model":[],"class_list":["post-146874","plugin","type-plugin","status-publish","hentry","plugin_tags-activities","plugin_tags-fitness","plugin_tags-import","plugin_tags-strava","plugin_tags-webhooks","plugin_category-utilities-and-tools","plugin_contributors-mirceatm","plugin_committers-mirceatm"],"banners":{"banner":"https:\/\/ps.w.org\/nmr-strava-activities\/assets\/banner-772x250.jpg?rev=2600854","banner_2x":false,"banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/nmr-strava-activities\/assets\/icon-128x128.jpg?rev=2600854","icon_2x":"https:\/\/ps.w.org\/nmr-strava-activities\/assets\/icon-256x256.jpg?rev=2600854","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/nmr-strava-activities\/assets\/screenshot-1.jpg?rev=2600854","caption":"Placeholder: Settings \u2192 Strava NMR (replace with a real screenshot in the WordPress.org <code>assets<\/code> folder when publishing)."},{"src":"https:\/\/ps.w.org\/nmr-strava-activities\/assets\/screenshot-2.jpg?rev=2600854","caption":"Placeholder: Example of activity data \/ <code>[strava_nmr_table]<\/code> output (replace with a real screenshot on WordPress.org)."}],"raw_content":"<!--section=description-->\n<p><strong>NMR Strava activities<\/strong> imports athlete activities into your WordPress site as soon as Strava records them\u2014no slow polling. Data is stored locally; developers can react with actions and filters for custom workflows, leaderboards, or integrations.<\/p>\n\n<p><strong>Why webhooks?<\/strong> Strava can <a href=\"https:\/\/developers.strava.com\/docs\/webhooks\/\">notify your site<\/a> when an activity is created or deleted. This plugin subscribes to those events, then fetches full activity details with OAuth and saves them to custom database tables.<\/p>\n\n<p><strong>You will need:<\/strong><\/p>\n\n<ul>\n<li>A <a href=\"https:\/\/www.strava.com\/settings\/api\">Strava API application<\/a> (Client ID and Client Secret)<\/li>\n<li>A page or post containing the <strong>[strava_nmr]<\/strong> shortcode; its URL must match <strong>Redirect URI<\/strong> in both Strava and this plugin\u2019s settings<\/li>\n<\/ul>\n\n<p><strong>Configure the plugin:<\/strong> WordPress admin \u2192 <strong>Settings \u2192 Strava NMR<\/strong><\/p>\n\n<ul>\n<li><strong>Strava client id<\/strong> \u2014 from your Strava API application<\/li>\n<li><strong>Strava client secret<\/strong> \u2014 from your Strava API application<\/li>\n<li><strong>Redirect URI<\/strong> \u2014 full URL of the page\/post where <strong>[strava_nmr]<\/strong> appears (must match Strava\u2019s Authorization Callback Domain \/ redirect settings)<\/li>\n<li><strong>Webhook callback url<\/strong> \u2014 filled automatically; should look like <code>https:\/\/yoursite.com\/wp-admin\/admin-ajax.php?action=nmr-strava-callback&amp;<\/code> (keep the trailing <code>&amp;<\/code> if your copy includes it)<\/li>\n<li><strong>Verify token<\/strong> \u2014 a secret string you choose; used when Strava validates your webhook subscription<\/li>\n<\/ul>\n\n<p>After saving, use <strong>Activate Strava Webhook<\/strong>. On success, <strong>Plugin status<\/strong> shows something like: <code>Strava webhook subscription id = 109463<\/code>.<\/p>\n\n<p><strong>Data and privacy<\/strong><\/p>\n\n<p>Activities and tokens are stored in your WordPress database. See <strong>Privacy Notices<\/strong> below. For GDPR or similar obligations, ensure your site policy explains this processing.<\/p>\n\n<p><strong>Developer hooks<\/strong><\/p>\n\n<p>When an activity is saved or removed, other code can listen:<\/p>\n\n<pre><code>do_action('strava_nmr_activity_changed', 'update', $activity_data);\n\ndo_action('strava_nmr_activity_changed', 'delete', $payload);\n<\/code><\/pre>\n\n<p><strong>Filter which activities are saved<\/strong> using the activity type (single string, e.g. <code>Run<\/code>):<\/p>\n\n<pre><code>`php\n<\/code><\/pre>\n\n<p>function nmr_example_save_only_runs( $activity_type ) {\n    if ( strcasecmp( 'Run', $activity_type ) === 0 || strcasecmp( 'VirtualRun', $activity_type ) === 0 ) {\n        return $activity_type;\n    }\n    return false;\n}\nadd_filter( 'nmr_strava_save_activity', 'nmr_example_save_only_runs' );\n    `<\/p>\n\n<p><strong>Filter using the full Strava activity array<\/strong> (return <code>false<\/code> to skip import):<\/p>\n\n<pre><code>`php\n<\/code><\/pre>\n\n<p>add_filter( 'nmr_strava_save_activity_full', function ( $activity ) {\n    if ( ! empty( $activity['manual'] ) ) {\n        return false;\n    }\n    return $activity;\n} );\n    `<\/p>\n\n<p>Supported Strava activity types include: AlpineSki, BackcountrySki, Canoeing, Crossfit, EBikeRide, Elliptical, Golf, Handcycle, Hike, IceSkate, InlineSkate, Kayaking, Kitesurf, NordicSki, Ride, RockClimbing, RollerSki, Rowing, Run, Sail, Skateboard, Snowboard, Snowshoe, Soccer, StairStepper, StandUpPaddling, Surfing, Swim, Velomobile, VirtualRide, VirtualRun, Walk, WeightTraining, Wheelchair, Windsurf, Workout, Yoga.<\/p>\n\n<p><strong>Shortcodes<\/strong><\/p>\n\n<ul>\n<li><code>[strava_nmr]<\/code> \u2014 OAuth connect flow (optional attributes for labels and <code>require_login<\/code>)<\/li>\n<li><code>[strava_nmr_connect]<\/code> \/ <code>[strava_nmr_disconnect]<\/code> \u2014 logged-in connect\/disconnect UI<\/li>\n<li><code>[strava_nmr_table top=\"100\"]<\/code> \u2014 simple HTML table of stored activities (default limit 100)<\/li>\n<\/ul>\n\n<p><strong>Official listing<\/strong><\/p>\n\n<p>Install from <a href=\"https:\/\/wordpress.org\/plugins\/nmr-strava-activities\/\">WordPress.org\/plugins\/nmr-strava-activities<\/a>. More info: <a href=\"https:\/\/namir.ro\/strava-activities\/\">Plugin URI<\/a>.<\/p>\n\n<p>If this plugin saves you time, consider <a href=\"https:\/\/paypal.me\/mirceatm\">making a donation<\/a>.<\/p>\n\n<h4>Privacy Notices<\/h4>\n\n<p>This plugin stores data received from Strava\u2014which may include personal information\u2014in your site\u2019s database. You are responsible for describing this in your privacy policy and for any consent or legal basis required in your jurisdiction.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Install from the <a href=\"https:\/\/wordpress.org\/plugins\/nmr-strava-activities\/\">plugin directory<\/a> or upload the <code>nmr-strava-activities<\/code> folder to <code>\/wp-content\/plugins\/<\/code>.<\/li>\n<li>Activate the plugin through the <strong>Plugins<\/strong> screen in WordPress.<\/li>\n<li>Create a Strava API application and configure <strong>Settings \u2192 Strava NMR<\/strong>.<\/li>\n<li>Add <strong>[strava_nmr]<\/strong> to a public page; set that page\u2019s URL as <strong>Redirect URI<\/strong> in Strava and in the plugin.<\/li>\n<li>Save settings, then click <strong>Activate Strava Webhook<\/strong> and confirm <strong>Plugin status<\/strong> shows a subscription id.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"do%20i%20need%20a%20strava%20api%20application%3F\"><h3>Do I need a Strava API application?<\/h3><\/dt>\n<dd><p>Yes. Create one at <a href=\"https:\/\/www.strava.com\/settings\/api\">strava.com\/settings\/api<\/a>. You need the Client ID, Client Secret, and the Redirect URI must match the page where you use the shortcode.<\/p><\/dd>\n<dt id=\"why%20must%20the%20redirect%20uri%20match%20exactly%3F\"><h3>Why must the Redirect URI match exactly?<\/h3><\/dt>\n<dd><p>OAuth requires the same redirect URL during authorization that you registered with Strava. A mismatch causes \u201cinvalid redirect\u201d or similar errors when users connect.<\/p><\/dd>\n<dt id=\"what%20is%20the%20webhook%20callback%20url%20for%3F\"><h3>What is the webhook callback URL for?<\/h3><\/dt>\n<dd><p>Strava sends HTTP notifications to that URL (your site\u2019s <code>admin-ajax.php<\/code> with <code>action=nmr-strava-callback<\/code>). You normally leave the default value. It must be reachable over HTTPS in production.<\/p><\/dd>\n<dt id=\"what%20is%20the%20verify%20token%3F\"><h3>What is the verify token?<\/h3><\/dt>\n<dd><p>A shared secret between your site and Strava during webhook subscription. It can be any string you choose; use the same value in the plugin and when Strava validates the subscription (GET challenge).<\/p><\/dd>\n<dt id=\"webhooks%20vs%20polling\"><h3>Webhooks vs polling<\/h3><\/dt>\n<dd><p>This plugin uses <strong>webhooks<\/strong> so new activities are processed when Strava pushes an event. You are not required to run a cron job to poll Strava for new data.<\/p><\/dd>\n<dt id=\"does%20this%20work%20on%20multisite%3F\"><h3>Does this work on multisite?<\/h3><\/dt>\n<dd><p>The plugin can be activated per site. Options and tables are per-site (<code>$wpdb<\/code> prefix). If you use <code>get_site_option<\/code> \/ <code>update_option<\/code> inconsistently for version checks, consult a developer for multisite edge cases.<\/p><\/dd>\n<dt id=\"activities%20not%20appearing\"><h3>Activities not appearing<\/h3><\/dt>\n<dd><p>Check that the webhook is active (subscription id in <strong>Plugin status<\/strong>), the athlete has connected via your site, Strava sent a <strong>create<\/strong> event, and your filters (<code>nmr_strava_save_activity<\/code> \/ <code>nmr_strava_save_activity_full<\/code>) do not return <code>false<\/code> for that activity.<\/p><\/dd>\n<dt id=\"gdpr%20and%20privacy\"><h3>GDPR and privacy<\/h3><\/dt>\n<dd><p>You store Strava-derived data locally. Disclose this to users and athletes; obtain consent where required. See <strong>Privacy Notices<\/strong> above.<\/p><\/dd>\n<dt id=\"where%20do%20i%20get%20support%3F\"><h3>Where do I get support?<\/h3><\/dt>\n<dd><p>Use the <a href=\"https:\/\/wordpress.org\/support\/plugin\/nmr-strava-activities\/\">WordPress.org support forum<\/a> for this plugin. See <code>docs\/SUPPORT.md<\/code> in the plugin package for maintainer notes (response rhythm, reviews).<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.12<\/h4>\n\n<ul>\n<li>Readme: stronger short description, tags, FAQ, installation path, developer examples aligned with code<\/li>\n<li>Documentation: WordPress.org listing notes, support and landing-page guides (<code>docs\/<\/code>)<\/li>\n<li>WordPress.org visual assets: banners, icons, screenshot placeholders in <code>.wordpress-org\/<\/code><\/li>\n<\/ul>\n\n<h4>1.0.11<\/h4>\n\n<ul>\n<li>Update column <code>activities.external_id<\/code> from not null to null - looks like a strava manual entry will generate null <code>external_id<\/code><\/li>\n<li>Update SQL string to use string interpolation for table name<\/li>\n<\/ul>\n\n<h4>1.0.10<\/h4>\n\n<ul>\n<li>Update column <code>activities.name<\/code> to <code>text<\/code><\/li>\n<\/ul>\n\n<h4>1.0.9<\/h4>\n\n<ul>\n<li>Update column <code>activities.raw_activity<\/code> to <code>mediumtext<\/code><\/li>\n<\/ul>\n\n<h4>1.0.8<\/h4>\n\n<ul>\n<li>Fixed XSS in <code>[strava_nmr_connect]<\/code><\/li>\n<\/ul>\n\n<h4>1.0.7<\/h4>\n\n<ul>\n<li>Updated code according to wordpress code review.<\/li>\n<\/ul>\n\n<h4>1.0.6<\/h4>\n\n<ul>\n<li>Added <code>nmr_strava_save_activity_full<\/code> filter that sends the entire Strava data as array. One can use it to filter out manual activities, for instance.<\/li>\n<li>Remove dangling options by the name <code>nmr-strava-%<\/code><\/li>\n<li>Save <code>subscription_id<\/code> once we read it from Strava<\/li>\n<\/ul>\n\n<h4>1.0.5<\/h4>\n\n<ul>\n<li>Added top property to shortcode <code>[strava_nmr_table top=10]<\/code>. Default value if 100.<\/li>\n<li><code>[strava_nmr_table top=10]<\/code> shows km and minutes instead of meters and seconds.<\/li>\n<li>Activate Strava will also save the settings.<\/li>\n<\/ul>\n\n<h4>1.0.4<\/h4>\n\n<ul>\n<li>Added simple shortcode to list activities received from Strava: <code>[strava_nmr_table]<\/code><\/li>\n<\/ul>\n\n<h4>1.0.3<\/h4>\n\n<ul>\n<li>Store Strava username, firstname, lastname and profile link<\/li>\n<li>Delete duplicate rows<\/li>\n<\/ul>\n\n<h4>1.0.2<\/h4>\n\n<ul>\n<li>Fixed strava activity import when there is no associated wordpress user.<\/li>\n<li>Add filter <code>nmr_strava_save_activity<\/code><\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>Fixed option save<\/li>\n<li>Add button to deactivate Strava subscription<\/li>\n<li>Removed use of PHP session<\/li>\n<li>Allow Strava activities from anonymous visitors (un-registered users) <\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial version.<\/li>\n<\/ul>","raw_excerpt":"Sync Strava activities into WordPress in real time via webhooks\u2014stored in your database with hooks for themes and plugins.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/146874","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=146874"}],"author":[{"embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/mirceatm"}],"wp:attachment":[{"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=146874"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=146874"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=146874"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=146874"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=146874"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=146874"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}