diff --git a/ui/component/viewers/videoViewer/index.js b/ui/component/viewers/videoViewer/index.js
index 52fe1db17..29def1a40 100644
--- a/ui/component/viewers/videoViewer/index.js
+++ b/ui/component/viewers/videoViewer/index.js
@@ -9,13 +9,14 @@ import { withRouter } from 'react-router';
 import { doClaimEligiblePurchaseRewards } from 'redux/actions/rewards';
 import { makeSelectClientSetting, selectHomepageData } from 'redux/selectors/settings';
 import { toggleVideoTheaterMode, doSetClientSetting } from 'redux/actions/settings';
-import { selectUserVerifiedEmail } from 'redux/selectors/user';
+import { selectUserVerifiedEmail, selectUser } from 'redux/selectors/user';
 
 const select = (state, props) => {
   const { search } = props.location;
   const urlParams = new URLSearchParams(search);
   const autoplay = urlParams.get('autoplay');
   const position = urlParams.get('t') !== null ? urlParams.get('t') : makeSelectContentPositionForUri(props.uri)(state);
+  const userId = selectUser(state).id;
 
   return {
     autoplayIfEmbedded: Boolean(autoplay),
@@ -29,6 +30,7 @@ const select = (state, props) => {
     claim: makeSelectClaimForUri(props.uri)(state),
     homepageData: selectHomepageData(state),
     authenticated: selectUserVerifiedEmail(state),
+    userId: userId,
   };
 };
 
diff --git a/ui/component/viewers/videoViewer/internal/plugins/videojs-recsys/plugin.js b/ui/component/viewers/videoViewer/internal/plugins/videojs-recsys/plugin.js
new file mode 100644
index 000000000..ee1ad8009
--- /dev/null
+++ b/ui/component/viewers/videoViewer/internal/plugins/videojs-recsys/plugin.js
@@ -0,0 +1,136 @@
+// Created by xander on 6/21/2021
+import videojs from 'video.js/dist/video.min.js';
+const VERSION = '0.0.1';
+
+const recsysEndpoint = 'https://clickstream.odysee.com/log/video/view';
+const recsysId = 'lighthouse-v0';
+
+/* RecSys */
+const RecsysData = {
+  event: {
+    start: 0,
+    stop: 1,
+    scrub: 2,
+    speed: 3,
+  },
+};
+
+function newRecsysEvent(eventType, offset, arg) {
+  if (arg) {
+    return {
+      event: eventType,
+      offset: offset,
+      arg: arg,
+    };
+  } else {
+    return {
+      event: eventType,
+      offset: offset,
+    };
+  }
+}
+
+function sendRecsysEvent(recsysEvent) {
+  const requestOptions = {
+    method: 'POST',
+    headers: { 'Content-Type': 'application/json' },
+    body: JSON.stringify(recsysEvent),
+  };
+
+
+  fetch(recsysEndpoint, requestOptions)
+    .then((response) => response.json())
+    .then((data) => {
+      console.log(`Recsys response data:`, data);
+    });
+}
+
+const defaults = {
+  endpoint: recsysEndpoint,
+  recsysId: recsysId,
+  videoId: '0',
+  userId: '0',
+  debug: false,
+};
+
+const Component = videojs.getComponent('Component');
+const registerPlugin = videojs.registerPlugin || videojs.plugin;
+
+class RecsysPlugin extends Component {
+  constructor(player, options) {
+    super(player, options);
+
+    // Plugin started
+    console.log(`created recsys plugin for: videoId:${options.videoId}, userId:${options.userId}`);
+
+    // To help with debugging, we'll add a global vjs object with the video js player
+    window.vjs = player;
+
+    this.player = player;
+
+    // Plugin event listeners
+    player.on('playing', (event) => this.onPlay(event));
+    player.on('pause', (event) => this.onPause(event));
+    player.on('ended', (event) => this.onEnded(event));
+    player.on('ratechange', (event) => this.onRateChange(event));
+    player.on('seeking', (event) => this.onSeeking(event));
+  }
+
+  onPlay(event) {
+    const recsysEvent = newRecsysEvent(RecsysData.event.start, this.player.currentTime());
+    this.log('onPlay', recsysEvent);
+    sendRecsysEvent(recsysEvent);
+  }
+
+  onPause(event) {
+    const recsysEvent = newRecsysEvent(RecsysData.event.stop, this.player.currentTime());
+    this.log('onPause', recsysEvent);
+    sendRecsysEvent(recsysEvent);
+  }
+
+  onEnded(event) {
+    const recsysEvent = newRecsysEvent(RecsysData.event.stop, this.player.currentTime());
+    this.log('onEnded', recsysEvent);
+    sendRecsysEvent(recsysEvent);
+  }
+
+  onRateChange(event) {
+    const recsysEvent = newRecsysEvent(RecsysData.event.speed, this.player.currentTime());
+    this.log('onRateChange', recsysEvent);
+    sendRecsysEvent(recsysEvent);
+  }
+
+  onSeeking(event) {
+    const recsysEvent = newRecsysEvent(RecsysData.event.scrub, this.player.currentTime());
+    this.log('onSeeking', recsysEvent);
+    sendRecsysEvent(recsysEvent);
+  }
+
+  log(...args) {
+    console.log(`Recsys Debug:`, JSON.stringify(args));
+  }
+}
+
+videojs.registerComponent('recsys', RecsysPlugin);
+
+const onPlayerReady = (player, options) => {
+  player.recsys = new RecsysPlugin(player, options);
+};
+
+/**
+ * Initialize the plugin.
+ *
+ * @function plugin
+ * @param    {Object} [options={}]
+ */
+const plugin = function(options) {
+  this.ready(() => {
+    onPlayerReady(this, videojs.mergeOptions(defaults, options));
+  });
+};
+
+plugin.VERSION = VERSION;
+
+registerPlugin('recsys', plugin);
+
+export default plugin;
diff --git a/ui/component/viewers/videoViewer/internal/videojs.jsx b/ui/component/viewers/videoViewer/internal/videojs.jsx
index 6df222ca6..167bd93a8 100644
--- a/ui/component/viewers/videoViewer/internal/videojs.jsx
+++ b/ui/component/viewers/videoViewer/internal/videojs.jsx
@@ -9,6 +9,7 @@ import eventTracking from 'videojs-event-tracking';
 import * as OVERLAY from './overlays';
 import './plugins/videojs-mobile-ui/plugin';
 import hlsQualitySelector from './plugins/videojs-hls-quality-selector/plugin';
+import recsys from './plugins/videojs-recsys/plugin';
 import qualityLevels from 'videojs-contrib-quality-levels';
 import isUserTyping from 'util/detect-typing';
 
@@ -50,6 +51,7 @@ type Props = {
   autoplay: boolean,
   toggleVideoTheaterMode: () => void,
   adUrl: ?string,
+  claimId: ?string,
 };
 
 // type VideoJSOptions = {
@@ -121,6 +123,10 @@ if (!Object.keys(videojs.getPlugins()).includes('qualityLevels')) {
   videojs.registerPlugin('qualityLevels', qualityLevels);
 }
 
+if (!Object.keys(videojs.getPlugins()).includes('recsys')) {
+  videojs.registerPlugin('recsys', recsys);
+}
+
 // ****************************************************************************
 // LbryVolumeBarClass
 // ****************************************************************************
@@ -180,6 +186,8 @@ export default React.memo<Props>(function VideoJs(props: Props) {
     onPlayerReady,
     toggleVideoTheaterMode,
     adUrl,
+    claimId,
+    userId,
   } = props;
 
   const [reload, setReload] = useState('initial');
@@ -578,6 +586,12 @@ export default React.memo<Props>(function VideoJs(props: Props) {
         displayCurrentQuality: true,
       });
 
+      // Add recsys plugin
+      player.recsys({
+        videoId: claimId,
+        userId: userId,
+      });
+
       // Update player source
       player.src({
         src: finalSource,
diff --git a/ui/component/viewers/videoViewer/view.jsx b/ui/component/viewers/videoViewer/view.jsx
index 76158ee30..7179ac1ef 100644
--- a/ui/component/viewers/videoViewer/view.jsx
+++ b/ui/component/viewers/videoViewer/view.jsx
@@ -24,48 +24,6 @@ import { useHistory } from 'react-router';
 const PLAY_TIMEOUT_ERROR = 'play_timeout_error';
 const PLAY_TIMEOUT_LIMIT = 2000;
 
-/* TODO: Move constants elsewhere */
-const recsysEndpoint = 'https://clickstream.odysee.com/log/video/view';
-const recsysId = 'lighthouse-v0';
-
-/* RecSys */
-const Recsys = {
-  event: {
-    start: 0,
-    stop: 1,
-    scrub: 2,
-    speed: 3,
-  },
-};
-
-function newRecsysEvent(eventType, offset, arg) {
-  if (arg) {
-    return {
-      event: eventType,
-      offset: offset,
-      arg: arg,
-    };
-  } else {
-    return {
-      event: eventType,
-      offset: offset,
-    };
-  }
-}
-
-function sendRecsysEvent(recsysEvent) {
-  const requestOptions = {
-    method: 'POST',
-    headers: { 'Content-Type': 'application/json' },
-    body: JSON.stringify(recsysEvent),
-  };
-  fetch(recsysEndpoint, requestOptions)
-    .then((response) => response.json())
-    .then((data) => {
-      console.log(`Recsys response data:`, data);
-    });
-}
-
 type Props = {
   position: number,
   changeVolume: (number) => void,
@@ -89,6 +47,7 @@ type Props = {
   toggleVideoTheaterMode: () => void,
   setVideoPlaybackRate: (number) => void,
   authenticated: boolean,
+  userId: number,
   homepageData: {
     PRIMARY_CONTENT_CHANNEL_IDS?: Array<string>,
     ENLIGHTENMENT_CHANNEL_IDS?: Array<string>,
@@ -130,6 +89,7 @@ function VideoViewer(props: Props) {
     setVideoPlaybackRate,
     homepageData,
     authenticated,
+    userId,
   } = props;
   const {
     PRIMARY_CONTENT_CHANNEL_IDS = [],
@@ -186,14 +146,6 @@ function VideoViewer(props: Props) {
     };
   }, [embedded, videoPlaybackRate]);
 
-  // Used to detect and send recsys events
-  useEffect(() => {
-    history.listen((location) => {
-      console.log(`You changed the page to: ${location.pathname}`);
-      // todo: recsys videoid change goes here
-    });
-  }, [history]);
-
   function doTrackingBuffered(e: Event, data: any) {
     fetch(source, { method: 'HEAD' }).then((response) => {
       data.playerPoweredBy = response.headers.get('x-powered-by');
@@ -249,8 +201,6 @@ function VideoViewer(props: Props) {
       clearPosition(uri);
     } else {
       savePosition(uri, player.currentTime());
-      const rsevent = newRecsysEvent(Recsys.event.scrub, player.currentTime());
-      sendRecsysEvent(rsevent);
     }
   }
 
@@ -306,7 +256,7 @@ function VideoViewer(props: Props) {
     player.on('tracking:buffered', doTrackingBuffered);
     player.on('tracking:firstplay', doTrackingFirstPlay);
     player.on('ended', onEnded);
-    player.on('play', onPlay);
+    player.on('play', () => onPlay(player));
     player.on('pause', () => onPause(player));
     player.on('dispose', () => onDispose(player));
 
@@ -393,6 +343,8 @@ function VideoViewer(props: Props) {
           startMuted={autoplayIfEmbedded}
           toggleVideoTheaterMode={toggleVideoTheaterMode}
           autoplay={!embedded || autoplayIfEmbedded}
+          claimId={claimId}
+          userId={userId}
         />
       )}
     </div>