Socket
Socket
Sign inDemoInstall

soundcloud-iframe-analytics

Package Overview
Dependencies
0
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.0.4 to 1.0.5

2

dist/sia.min.js

@@ -1,2 +0,2 @@

!function(n){var e={};function t(o){if(e[o])return e[o].exports;var i=e[o]={i:o,l:!1,exports:{}};return n[o].call(i.exports,i,i.exports,t),i.l=!0,i.exports}t.m=n,t.c=e,t.d=function(n,e,o){t.o(n,e)||Object.defineProperty(n,e,{configurable:!1,enumerable:!0,get:o})},t.r=function(n){Object.defineProperty(n,"__esModule",{value:!0})},t.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(e,"a",e),e},t.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},t.p="",t(t.s=1)}([function(n,e,t){e.loadScript=t(3),e.loadScriptPromised=t(2)},function(n,e,t){"use strict";t.r(e);var o=t(0),i=!1,r=!0,u=void 0;function c(n,e,t,o){if(r){var c=function(){if(u)return u;"function"==typeof window.gtag?u=a.GlobalSiteTag:"function"==typeof window.ga?u=a.GA:"_gaq"in window&&"function"==typeof window._gaq.push&&(u=a.Legacy);return u||(r=!1,null)}();c&&(i&&console.info('Tracking Event: category "'+n+'" action "'+e+'" label "'+t+'" value "'+o+'"'),c.event(n,e,t,o))}}var a={GlobalSiteTag:{event:function(n,e,t,o){window.gtag("event",e,{event_category:n,event_label:t,value:o})}},GA:{event:function(n,e,t,o){window.ga("send","event",n,e,t)}},Legacy:{event:function(n,e,t,o){window._gaq.push(["_trackEvent",n,e,t])}}},d="https://w.soundcloud.com/player/api.js",f="soundcloud.com",s="SoundCloud";function l(){var n=[];b(document.getElementsByTagName("iframe"),function(e){e.hasAttribute("src")&&e.getAttribute("src").indexOf(f)>-1&&n.push(e)}),0!==n.length&&o.loadScript(d,function(){"SC"in window&&b(n,function(n){!function(n){var e=SC.Widget.Events,t=!1,o="",i={},r=void 0;n.bind(e.READY,function(){}),n.bind(e.ERROR,function(){c(s,"Error",o)}),n.bind(e.PLAY_PROGRESS,function(){t||(t=!0,setTimeout(function(){t=!1,n.getCurrentSound(function(n){o!==n.title&&(o=n.title,i={})})},0===o.length?0:2500))}),n.bind(e.PLAY,function(){n.getCurrentSound(function(n){o=n.title,!(r=p(i,n.title)).started||r.finished?(r.started=!0,r.finished=!1,r.paused=!1,r.scrubbed=!1,c(s,"Playback started",o)):r.paused&&(r.paused=!1,c(s,"Playback resumed",o))})}),n.bind(e.PAUSE,function(){r=p(i,o),n.getCurrentSound(function(n){n.title!==r.id||r.finished||(r.paused=!0,c(s,"Playback paused",o))})}),n.bind(e.SEEK,function(){(r=p(i,o)).paused||r.finished||(r.scrubbed=!0,c(s,"Playback scrubbed",o))}),n.bind(e.FINISH,function(){if(!(r=p(i,o)).finished){r.finished=!0;var n=r.scrubbed?"Played in full with scrubbing":"Played in full";c(s,n,o)}})}(SC.Widget(n))})})}function p(n,e){return n.hasOwnProperty(e)||(n[e]={id:e,started:!1,paused:!1,scrubbed:!1,finished:!1}),n[e]}function b(n,e){for(var t=0,o=n.length;t<o;++t)e(n[t])}document.addEventListener("DOMContentLoaded",function n(){l(),document.removeEventListener("DOMContentLoaded",n)})},function(n,e){n.exports=function(n,e){var t,o,i=document;return new Promise(function(r,u){o=i.createElement("script"),t=i.getElementsByTagName("script")[0],e&&Object.keys(e).forEach(function(n){o[n]=e[n]}),o.async=1,o.src=n,o.onload=function(){r()},o.onerror=function(){u(new Error("failed to load: "+n))},t.parentNode.insertBefore(o,t)})}},function(n,e){n.exports=function(n,e,t){var o,i,r=document;i=r.createElement("script"),o=r.getElementsByTagName("script")[0],t&&Object.keys(t).forEach(function(n){i[n]=t[n]}),i.async=1,i.src=n,i.onload=function(){e()},i.onerror=function(){e(new Error("failed to load: "+n))},o.parentNode.insertBefore(i,o)}}]);
!function(e){var n={};function t(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,t),r.l=!0,r.exports}t.m=e,t.c=n,t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:o})},t.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="",t(t.s=1)}([function(e,n,t){n.loadScript=t(3),n.loadScriptPromised=t(2)},function(e,n,t){"use strict";t.r(n);var o=t(0),r=!1,i=!0,u=void 0;function c(e,n,t,o){if(i){var c=function(){if(u)return u;"function"==typeof window.gtag?u=s.GlobalSiteTag:"function"==typeof window.ga?u=s.GA:"_gaq"in window&&"function"==typeof window._gaq.push&&(u=s.Legacy);return u||(i=!1,null)}();c&&(r&&console.info('Tracking Event: category "'+e+'" action "'+n+'" label "'+t+'" value "'+o+'"'),c.event(e,n,t,o))}}var s={GlobalSiteTag:{event:function(e,n,t,o){window.gtag("event",n,{event_category:e,event_label:t,value:o})}},GA:{event:function(e,n,t,o){window.ga("send","event",e,n,t)}},Legacy:{event:function(e,n,t,o){window._gaq.push(["_trackEvent",e,n,t])}}},d="https://w.soundcloud.com/player/api.js",a="soundcloud.com",f="SoundCloud";function p(){var e=[];if(g(document.getElementsByTagName("iframe"),function(n){n.hasAttribute("src")&&n.getAttribute("src").indexOf(a)>-1&&e.push(n)}),0!==e.length){var n=function(){g(e,function(e){!function(e){var n=SC.Widget.Events,t=!1,o="",r=0,i={},u=void 0;e.bind(n.READY,function(){}),e.bind(n.ERROR,function(){c(f,"Error",o)}),e.bind(n.PLAY_PROGRESS,function(n){u&&u.id===n.soundId&&function(e,n){if("number"!=typeof n.relativePosition)return;e.progress=Math.round(100*n.relativePosition);var t=void 0;e.progress>=99&&e.progstep<4?(t="4/4",e.progstep=4):e.progress>=75&&e.progstep<3?(t="3/4",e.progstep=3):e.progress>=50&&e.progstep<2?(t="2/4",e.progstep=2):e.progress>=25&&e.progstep<1&&(t="1/4",e.progstep=1);"string"==typeof t&&(e.scrubbed&&(t+=" with scrubbing"),c(f,"Progress "+t,e.title))}(u,n),t||(t=!0,setTimeout(function(){t=!1,e.getCurrentSound(function(e){r!==e.id&&(o=e.title,r=e.id,i={})})},0===r?0:2500))}),e.bind(n.PLAY,function(){e.getCurrentSound(function(e){o=e.title,r=e.id,!(u=l(i,e.title,e.id)).started||u.finished?(u.started=!0,u.finished=!1,u.paused=!1,u.scrubbed=!1,u.progress=0,u.progstep=0,c(f,"Playback started",o)):u.paused&&(u.paused=!1,c(f,"Playback resumed",o))})}),e.bind(n.PAUSE,function(){u=l(i,o,r),e.getCurrentSound(function(e){e.id!==u.id||u.finished||(u.paused=!0,c(f,"Playback paused",o))})}),e.bind(n.SEEK,function(){(u=l(i,o,r)).scrubbed||u.paused||u.finished||(u.scrubbed=!0,c(f,"Playback scrubbed",o))}),e.bind(n.FINISH,function(){if(!(u=l(i,o,r)).finished){u.finished=!0;var e=u.scrubbed?"Played in full with scrubbing":"Played in full";c(f,e,o)}})}(SC.Widget(e))})};"SC"in window&&"function"==typeof SC.Widget?n():o.loadScript(d,n)}}function l(e,n,t){return e.hasOwnProperty(n)?0===e[n].id&&(e[n].id=t):e[n]={title:n,id:t,started:!1,paused:!1,scrubbed:!1,finished:!1,progress:0,progstep:0},e[n]}function g(e,n){for(var t=0,o=e.length;t<o;++t)n(e[t])}document.addEventListener("DOMContentLoaded",function e(){p(),document.removeEventListener("DOMContentLoaded",e)})},function(e,n){e.exports=function(e,n){var t,o,r=document;return new Promise(function(i,u){o=r.createElement("script"),t=r.getElementsByTagName("script")[0],n&&Object.keys(n).forEach(function(e){o[e]=n[e]}),o.async=1,o.src=e,o.onload=function(){i()},o.onerror=function(){u(new Error("failed to load: "+e))},t.parentNode.insertBefore(o,t)})}},function(e,n){e.exports=function(e,n,t){var o,r,i=document;r=i.createElement("script"),o=i.getElementsByTagName("script")[0],t&&Object.keys(t).forEach(function(e){r[e]=t[e]}),r.async=1,r.src=e,r.onload=function(){n()},r.onerror=function(){n(new Error("failed to load: "+e))},o.parentNode.insertBefore(r,o)}}]);
//# sourceMappingURL=sia.min.js.map
{
"name": "soundcloud-iframe-analytics",
"version": "1.0.4",
"version": "1.0.5",
"description": "Automated Google Analytics tracking of user interaction on embedded SoundCloud iframes",

@@ -5,0 +5,0 @@ "author": "Igor Zinken",

@@ -76,9 +76,16 @@ SoundCloud IFRAME Analytics

* _Playback scrubbed_
* _Progress (num)_
* _Progress (num) with scrubbing_
* _Played in full_
* _Played in full with scrubbing_
Where starts are counted only once per track (unless it has finished playback).
Scrubbed indicates that the user has dragged the playback to a different point in the track and thus
might have skipped sections.
Where:
* _starts_ are counted only once per track (unless it has finished playback, after which we can treat
it as a new play).
* _scrubbed_ and _with scrubbing_ indicates that the user has dragged the playback to a different point in the track and thus
might have skipped sections. You can use this to determine engagement. _Playback scrubbed_ is tracked only
once (unless track has finished playback and is restarted).
* _progress_ is tracked for every 25 % of the track that has been played, expected values for _(num)_ are: 1/4, 2/4, 3/4 and 4/4
## Development

@@ -85,0 +92,0 @@

@@ -30,12 +30,20 @@ import * as TinyScriptLoader from "tiny-script-loader";

// load the SoundCloud Widget API
// process all IFrames one by one and add event listeners and Analytics hooks
TinyScriptLoader.loadScript( SOUNDCLOUD_API_URL, () => {
if ( "SC" in window ) {
loop( playlists, ( playlist ) => {
const widget = SC.Widget( playlist );
attachSoundCloudAnalytics( widget );
});
}
});
const processIFrames = () => {
loop( playlists, ( playlist ) => {
const widget = SC.Widget( playlist );
attachSoundCloudAnalytics( widget );
});
};
// ensure the SoundCloud Widget API has been loaded
// after which the processing of the IFrames can start
if ( "SC" in window && typeof SC.Widget === "function" ) {
processIFrames();
}
else {
TinyScriptLoader.loadScript( SOUNDCLOUD_API_URL, processIFrames );
}
}

@@ -57,3 +65,3 @@

let hasTimeout = false, currentId = "", tracks = {}, vo;
let hasTimeout = false, currentTrackTitle = "", currentTrackId = 0, tracks = {}, vo;

@@ -72,7 +80,10 @@ // cache the id of the currently playing track as many events in the

widget.bind( ENUM.ERROR, () => {
trackEvent( ANALYTICS_EVENT_CATEGORY, "Error", currentId );
trackEvent( ANALYTICS_EVENT_CATEGORY, "Error", currentTrackTitle );
});
widget.bind( ENUM.PLAY_PROGRESS, () => {
widget.bind( ENUM.PLAY_PROGRESS, ( playerData ) => {
if ( vo && vo.id === playerData.soundId )
setTrackProgress( vo, playerData );
if ( hasTimeout )

@@ -93,4 +104,5 @@ return;

if ( currentId !== data.title ) {
currentId = data.title;
if ( currentTrackId !== data.id ) {
currentTrackTitle = data.title;
currentTrackId = data.id;
tracks = {};

@@ -100,3 +112,3 @@ }

}, ( currentId.length === 0 ) ? 0 : INTERVAL );
}, ( currentTrackId === 0 ) ? 0 : INTERVAL );
});

@@ -107,6 +119,9 @@

currentId = data.title;
vo = getSoundCloudTrackVO( tracks, data.title );
currentTrackTitle = data.title;
currentTrackId = data.id;
vo = getSoundCloudTrackVO( tracks, data.title, data.id );
if ( !vo.started || vo.finished ) {
vo.started = true;

@@ -116,7 +131,10 @@ vo.finished = false;

vo.scrubbed = false;
trackEvent( ANALYTICS_EVENT_CATEGORY, "Playback started", currentId );
vo.progress = 0;
vo.progstep = 0;
trackEvent( ANALYTICS_EVENT_CATEGORY, "Playback started", currentTrackTitle );
}
else if ( vo.paused ) {
vo.paused = false;
trackEvent( ANALYTICS_EVENT_CATEGORY, "Playback resumed", currentId );
trackEvent( ANALYTICS_EVENT_CATEGORY, "Playback resumed", currentTrackTitle );
}

@@ -129,3 +147,3 @@ });

widget.bind( ENUM.PAUSE, () => {
vo = getSoundCloudTrackVO( tracks, currentId );
vo = getSoundCloudTrackVO( tracks, currentTrackTitle, currentTrackId );

@@ -140,5 +158,5 @@ // do async check for current sound, if it is the same then

widget.getCurrentSound(( data ) => {
if ( data.title === vo.id && !vo.finished ) {
if ( data.id === vo.id && !vo.finished ) {
vo.paused = true;
trackEvent( ANALYTICS_EVENT_CATEGORY, "Playback paused", currentId );
trackEvent( ANALYTICS_EVENT_CATEGORY, "Playback paused", currentTrackTitle );
}

@@ -148,14 +166,14 @@ });

widget.bind( ENUM.SEEK, () => {
vo = getSoundCloudTrackVO( tracks, currentId );
if ( !vo.paused && !vo.finished ) {
vo = getSoundCloudTrackVO( tracks, currentTrackTitle, currentTrackId );
if ( !vo.scrubbed && !vo.paused && !vo.finished ) {
vo.scrubbed = true;
trackEvent( ANALYTICS_EVENT_CATEGORY, "Playback scrubbed", currentId );
trackEvent( ANALYTICS_EVENT_CATEGORY, "Playback scrubbed", currentTrackTitle );
}
});
widget.bind( ENUM.FINISH, () => {
vo = getSoundCloudTrackVO( tracks, currentId );
vo = getSoundCloudTrackVO( tracks, currentTrackTitle, currentTrackId );
if ( !vo.finished ) {
vo.finished = true;
const event = ( !vo.scrubbed ) ? "Played in full" : "Played in full with scrubbing";
trackEvent( ANALYTICS_EVENT_CATEGORY, event, currentId );
trackEvent( ANALYTICS_EVENT_CATEGORY, event, currentTrackTitle );
}

@@ -175,20 +193,69 @@ });

* @param {Object} tracks data store for the tracks
* @param {string} id identifier of the track
* @param {string} title of the track
* @param {number} id identifier of the track
* @returns {Object}
*/
function getSoundCloudTrackVO( tracks, id ) {
function getSoundCloudTrackVO( tracks, title, id ) {
if ( !tracks.hasOwnProperty( id )) {
tracks[ id ] = {
id: id,
started: false,
paused: false,
scrubbed: false,
finished: false
if ( !tracks.hasOwnProperty( title )) {
tracks[ title ] = {
title: title, // track title, used as label for Google Analytics
id: id, // track unique identifier on SoundCloud
started: false, // whether track has started its playback
paused: false, // whether track playback is paused
scrubbed: false, // whether track has been scrubbed during playback
finished: false, // whether track has finished its playback, e.g. reached the end
progress: 0, // current track playback progress (0 - 100 range)
progstep: 0 // the progress that has been tracked so far (4 steps, once every 25%)
};
}
return tracks[ id ];
else if ( tracks[ title ].id === 0 ) {
tracks[ title].id = id;
}
return tracks[ title ];
}
/**
* Get the track playback progress (in percent)
*
* @param {Object} vo SoundCloud Value Object
* @param {Object} playerData progress data Object
*/
function setTrackProgress( vo, playerData ) {
if ( typeof playerData.relativePosition !== "number" )
return;
vo.progress = Math.round( playerData.relativePosition * 100 );
// track once every 25 %
let doTrack = false, msg;
if ( vo.progress >= 99 && vo.progstep < 4 ) {
msg = "4/4";
vo.progstep = 4;
}
else if ( vo.progress >= 75 && vo.progstep < 3 ) {
msg = "3/4";
vo.progstep = 3;
}
else if ( vo.progress >= 50 && vo.progstep < 2 ) {
msg = "2/4";
vo.progstep = 2;
}
else if ( vo.progress >= 25 && vo.progstep < 1 ) {
msg = "1/4";
vo.progstep = 1;
}
if ( typeof msg === "string" ) {
if ( vo.scrubbed ) {
msg += " with scrubbing";
}
trackEvent( ANALYTICS_EVENT_CATEGORY, `Progress ${msg}`, vo.title );
}
}
/**
* Simple forEach() implementation that will

@@ -195,0 +262,0 @@ * go back a few old IE versions...

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc