Socket
Socket
Sign inDemoInstall

soundcloud-iframe-analytics

Package Overview
Dependencies
1
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.0.6 to 2.0.0

demo/index.ejs

2

dist/sia.min.js

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

!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,{enumerable:!0,get:o})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(t.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var r in e)t.d(o,r,function(n){return e[n]}.bind(null,r));return o},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=3)}([function(e,n,t){n.loadScript=t(1),n.loadScriptPromised=t(2)},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)}},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,t){"use strict";t.r(n);var o,r=t(0),i=t.n(r),u=!0;function d(e,n,t,r){if(u){var i=function(){if(o)return o;"function"==typeof window.gtag?o=c.GlobalSiteTag:"function"==typeof window.ga?o=c.GA:"_gaq"in window&&"function"==typeof window._gaq.push&&(o=c.Legacy);return o||(u=!1,null)}();i&&i.event(e,n,t,r)}}var c={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])}}};function s(){var e=document.getElementsByTagName("iframe"),n=[];if(f(e,(function(e){e.hasAttribute("src")&&e.getAttribute("src").indexOf("soundcloud.com")>-1&&n.push(e)})),0!==n.length){var t=function(){f(n,(function(e){!function(e){var n,t=SC.Widget.Events,o=!1,r="",i=0,u={};e.bind(t.READY,(function(){})),e.bind(t.ERROR,(function(){d("SoundCloud","Error",r)})),e.bind(t.PLAY_PROGRESS,(function(t){n&&n.id===t.soundId&&function(e,n){if("number"!=typeof n.relativePosition)return;var t;e.progress=function(e){return Math.round(100*e.relativePosition)}(n),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"),d("SoundCloud","Progress ".concat(t),e.title))}(n,t),o||(o=!0,setTimeout((function(){o=!1,e.getCurrentSound((function(e){i!==e.id&&(r=e.title,i=e.id,u={})}))}),0===i?0:2500))})),e.bind(t.PLAY,(function(){e.getCurrentSound((function(e){r=e.title,i=e.id,!(n=a(u,e.title,e.id)).started||n.finished?(n.started=!0,n.finished=!1,n.paused=!1,n.scrubbed=!1,n.progress=0,n.progstep=0,d("SoundCloud","Playback started",r)):n.paused&&(n.paused=!1,d("SoundCloud","Playback resumed",r))}))})),e.bind(t.PAUSE,(function(){n=a(u,r,i),e.getCurrentSound((function(e){e.id!==n.id||n.finished||(n.paused=!0,d("SoundCloud","Playback paused",r))}))})),e.bind(t.SEEK,(function(e){(n=a(u,r,i)).scrubbed||n.paused||n.finished||(n.scrubbed=!0,d("SoundCloud","Playback scrubbed",r))})),e.bind(t.FINISH,(function(){(n=a(u,r,i)).finished||(n.finished=!0,d("SoundCloud",n.scrubbed?"Played in full with scrubbing":"Played in full",r))}))}(SC.Widget(e))}))};"SC"in window&&"function"==typeof SC.Widget?t():i.a.loadScript("https://w.soundcloud.com/player/api.js",t)}}function a(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 f(e,n){for(var t=0,o=e.length;t<o;++t)n(e[t])}document.addEventListener("DOMContentLoaded",(function e(){s(),document.removeEventListener("DOMContentLoaded",e)}))}]);
!function(n){var t={};function e(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return n[r].call(o.exports,o,o.exports,e),o.l=!0,o.exports}e.m=n,e.c=t,e.d=function(n,t,r){e.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:r})},e.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},e.t=function(n,t){if(1&t&&(n=e(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var r=Object.create(null);if(e.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var o in n)e.d(r,o,function(t){return n[t]}.bind(null,o));return r},e.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return e.d(t,"a",t),t},e.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},e.p="",e(e.s=3)}([function(n,t,e){t.loadScript=e(1),t.loadScriptPromised=e(2)},function(n,t){n.exports=function(n,t,e){var r,o,i=document;o=i.createElement("script"),r=i.getElementsByTagName("script")[0],e&&Object.keys(e).forEach((function(n){o[n]=e[n]})),o.async=1,o.src=n,o.onload=function(){t()},o.onerror=function(){t(new Error("failed to load: "+n))},r.parentNode.insertBefore(o,r)}},function(n,t){n.exports=function(n,t){var e,r,o=document;return new Promise((function(i,u){r=o.createElement("script"),e=o.getElementsByTagName("script")[0],t&&Object.keys(t).forEach((function(n){r[n]=t[n]})),r.async=1,r.src=n,r.onload=function(){i()},r.onerror=function(){u(new Error("failed to load: "+n))},e.parentNode.insertBefore(r,e)}))}},function(n,t,e){"use strict";e.r(t),e.d(t,"init",(function(){return s})),e.d(t,"attachSoundCloudAnalytics",(function(){return f}));var r,o=e(0),i=e.n(o),u=!0;function d(n,t,e,o){if(u){var i=function(){if(r)return r;"function"==typeof window.gtag?r=c.GlobalSiteTag:"function"==typeof window.ga?r=c.GA:"_gaq"in window&&"function"==typeof window._gaq.push&&(r=c.Legacy);return r||(u=!1,null)}();i&&i.event(n,t,e,o)}}var c={GlobalSiteTag:{event:function(n,t,e,r){window.gtag("event",t,{event_category:n,event_label:e,value:r})}},GA:{event:function(n,t,e,r){window.ga("send","event",n,t,e)}},Legacy:{event:function(n,t,e,r){window._gaq.push(["_trackEvent",n,t,e])}}},a="SC"in window&&"function"==typeof window.SC.Widget?window.SC.Widget:null;function s(){return new Promise((function(n,t){var e=function(){var t=document.getElementsByTagName("iframe"),e=[];p(t,(function(n){n.hasAttribute("src")&&n.getAttribute("src").includes("soundcloud.com")&&e.push(n)}));var r=[];p(e,(function(n){r.push(f(n))})),n(r.filter(Boolean))};a?e():i.a.loadScript("https://w.soundcloud.com/player/api.js",(function(){a=a||window.SC.Widget,e()}),t)}))}function f(n){if(!n)return null;var t,e=n.getAttribute("data-sia"),r=n.getAttribute("src");if(e&&e===r)return!1;n.setAttribute("data-sia",r);try{t=a(n)}catch(n){return null}var o,i=a.Events,u=!1,c="",s=0,f={};return t.bind(i.ERROR,(function(){d("SoundCloud","Error",c)})),t.bind(i.PLAY_PROGRESS,(function(n){o&&o.id===n.soundId&&function(n,t){if("number"!=typeof t.relativePosition)return;var e;n.progress=function(n){return Math.round(100*n.relativePosition)}(t),n.progress>=99&&n.progstep<4?(e="4/4",n.progstep=4):n.progress>=75&&n.progstep<3?(e="3/4",n.progstep=3):n.progress>=50&&n.progstep<2?(e="2/4",n.progstep=2):n.progress>=25&&n.progstep<1&&(e="1/4",n.progstep=1);"string"==typeof e&&(n.scrubbed&&(e+=" with scrubbing"),d("SoundCloud","Progress ".concat(e),n.title))}(o,n),u||(u=!0,setTimeout((function(){u=!1,t.getCurrentSound((function(n){s!==n.id&&(c=n.title,s=n.id,f={})}))}),0===s?0:2500))})),t.bind(i.PLAY,(function(){t.getCurrentSound((function(n){c=n.title,s=n.id,!(o=l(f,n.title,n.id)).started||o.finished?(o.started=!0,o.finished=!1,o.paused=!1,o.scrubbed=!1,o.progress=0,o.progstep=0,d("SoundCloud","Playback started",c)):o.paused&&(o.paused=!1,d("SoundCloud","Playback resumed",c))}))})),t.bind(i.PAUSE,(function(){o=l(f,c,s),t.getCurrentSound((function(n){n.id!==o.id||o.finished||(o.paused=!0,d("SoundCloud","Playback paused",c))}))})),t.bind(i.SEEK,(function(n){(o=l(f,c,s)).scrubbed||o.paused||o.finished||(o.scrubbed=!0,d("SoundCloud","Playback scrubbed",c))})),t.bind(i.FINISH,(function(){(o=l(f,c,s)).finished||(o.finished=!0,d("SoundCloud",o.scrubbed?"Played in full with scrubbing":"Played in full",c))})),{element:n,widget:t,dispose:function(){[i.ERROR,i.PLAY_PROGRESS,i.PLAY,i.PAUSE,i.SEEK,i.FINISH].forEach((function(n){t.unbind(n)})),n.removeAttribute("data-sia")}}}function l(n,t,e){return n.hasOwnProperty(t)?0===n[t].id&&(n[t].id=e):n[t]={title:t,id:e,started:!1,paused:!1,scrubbed:!1,finished:!1,progress:0,progstep:0},n[t]}function p(n,t){for(var e=0,r=n.length;e<r;++e)t(n[e])}}]);
//# sourceMappingURL=sia.min.js.map
{
"name": "soundcloud-iframe-analytics",
"version": "1.0.6",
"description": "Automated Google Analytics tracking of user interaction on embedded SoundCloud iframes",
"version": "2.0.0",
"description": "Google Analytics tracking of user interaction on embedded SoundCloud iframes",
"author": "Igor Zinken",

@@ -11,3 +11,3 @@ "license": "MIT",

"build": "webpack -p --progress --mode production --config webpack.config.build.js",
"test": "webpack -p --progress --mode development --config webpack.config.test.js && npm run dev",
"test": "jest",
"prepublish": "npm run build"

@@ -24,3 +24,2 @@ },

"babel-loader": "8.1.0",
"chai": "^1.9.2",
"clean-webpack-plugin": "0.1.19",

@@ -32,12 +31,10 @@ "cross-env": "5.1.4",

"html-webpack-plugin": "3.2.0",
"mocha": "^7.1.2",
"mocha-loader": "^5.0.0",
"jest": "^26.1.0",
"node-sass": "^4.14.0",
"sass-loader": "7.0.1",
"sinon": "^2.3.4",
"style-loader": "0.21.0",
"url-loader": "1.0.1",
"webpack": "4.43.0",
"webpack-cli": "3.3.11",
"webpack-dev-server": ">=3.1.11",
"webpack": "^4.43.0",
"webpack-cli": "2.0.14",
"webpack-dev-server": "^3.11.0",
"webpack-merge": "4.1.2"

@@ -44,0 +41,0 @@ },

@@ -1,8 +0,6 @@

SoundCloud IFRAME Analytics
===========================
# SoundCloud iframe Analytics
A minimal library that attaches Google Analytics event tracking to user interactions
performed on embedded SoundCloud iframes, both on single tracks as well as playlists. It should
work from IE8 upwards - though the real concern with compatibility is probably restricted to the
requirements of the SoundCloud embed itself -
SoundCloud Iframe Analytics (SIA) is a minimal library that attaches Google Analytics event tracking
to user interactions performed on SoundCloud iframes embedded within your HTML page, both on single
tracks as well as full playlists.

@@ -13,3 +11,3 @@ This allows you to track user behaviour as well as have the events act as beacons to

Several versions of Google Analytics trackers are supported, namely:
Multiple versions of the Google Analytics tracker are supported, namely:

@@ -26,38 +24,83 @@ * Global Site Tag (gtag)

npm install soundcloud-iframe-analytics --save-dev
```
npm install soundcloud-iframe-analytics --save-dev
```
## How to integrate within your application
Firstly, embed the Analytics tracking code as provided by Google into your template(s).
First, embed the Analytics tracking code as provided by Google into your HTML template(s).
### The easy way, just drop in the JS file
Then, add a SoundCloud iframe embed similar to the below:
Embed the SoundCloud iframes according to the embed code provided by SoundCloud. You do not need to make
any changes to your markup. E.g. simply inject one or more instances of:
<iframe width="100%" height="300"
scrolling="no" frameborder="no"
src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/playlists/{STRING_ID}&amp;color=%23ff5500&amp;auto_play=false&amp;hide_related=false&amp;show_comments=true&amp;show_user=true&amp;show_reposts=false&amp;show_teaser=true">
```html
<iframe
width="100%" height="300"
scrolling="no" frameborder="no"
src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/playlists/{STRING_ID}&amp;color=%23ff5500&amp;auto_play=false&amp;hide_related=false&amp;show_comments=true&amp;show_user=true&amp;show_reposts=false&amp;show_teaser=true">
</iframe>
```
Include the minimized production version of the script (_./dist/sia.min.js_) at the bottom of your page
and the script will automatically attach event listeners to the iframes.
Basically, you embed the SoundCloud iframes according to the embed code provided by SoundCloud.
You do not need to make any changes to the generated markup.
### The easy way : automatically attach tracking to static HTML pages
When your HTML pages are static / contain the iframe content upon delivery, you can
easily attach the Analytics tracking by adding the following snippet to your JavaScript code:
```js
import { init } from "soundcloud-iframe-analytics";
async function readyHandler() {
document.removeEventListener( "DOMContentLoaded", readyHandler );
const embeds = await init();
}
document.addEventListener( "DOMContentLoaded", readyHandler );
```
The above will run once when the document finishes loading. It will then scan the document for
iframes with SoundCloud content and attach the listeners automatically. The returned value is
a list of successfully bound listeners for each iframe, where each value is wrapped inside
an object like so:
```js
{
element : HTMLIFrameElement,
widget : SC.Widget,
dispose : Function
}
```
In case you are wondering what those are good for, it's good to know that if your SoundCloud
content remains on the page throughout its lifetime, you can safely ignore these. But if you
are curious, you are likely someone who is looking for...
### The "I want full control" way
Alternatively, you can import the ES6 modules from the _./src_ folder and embed the library
within your custom application code. You can use this in case you already use the SoundCloud Widget
API to inject/control SoundCloud content in your page.
In case your page is an SPA that injects/removes SoundCloud iframes at runtime, you
need to keep track of additionally added iframes _after_ the document has finished loading.
You probably also want to clean up after yourself when you no longer need these iframes.
You can attach Analytics triggers to Widget events by passing an existing instance of _SC.Widget_ to
the _attachSoundCloudAnalytics()_ function of the _SoundCloud.js_ file, e.g.:
You can attach Analytics triggers to injected iframes by passing their reference to the
_attachSoundCloudAnalytics()_-method. Your pseudo code would look like:
```JavaScript
import { attachSoundCloudAnalytics } from "soundcloud-iframe-analytics/src/soundcloud/SoundCloud";
```js
import { init, attachSoundCloudAnalytics } from "soundcloud-iframe-analytics";
const existingWidget = ...; // SC.Widget instance created elsewhere in your application
attachSoundCloudAnalytics( existingWidget );
async function executedOnce() {
await init(); // loads SoundCloud SDK
}
function executeAfterNewIframeIsInjected( iframeReference ) {
const result = attachSoundCloudAnalytics( iframeReference );
if ( result !== null ) {
// SoundCloud Analytics attached successfully
// invoke dispose() when the iframe is no longer needed / removed from page
const { element, widget, dispose } = result;
}
}
```
Bob's your uncle.
And Bob's your uncle. SIA will automatically detect whether the same iframe is
passed for attachment of Analytics events and will deduplicate everything accordingly.

@@ -98,3 +141,5 @@ ## Event message format

npm install
```
npm install
```

@@ -107,7 +152,11 @@ ### Local development

npm run dev
```
npm run dev
```
### Creating a production build
npm run build
```
npm run build
```

@@ -118,13 +167,13 @@ Build output will be stored in _./dist_-folder.

Unit tests are run via Mocha, which is installed as a dependency, along
with Chai as the assertion library. You can run the tests by using:
Unit tests are run via Jest, which is installed as a dependency.
You can run the tests by using:
npm test
```
npm test
```
Unit tests go in the _./test_-folder. The file name for a unit test must
be equal to the file it is testing, but contain the suffix ".test",
e.g. _Functions.js_ will have a test file _Functions.test.js_.
be equal to the file it is testing, but contain the suffix ".spec.js",
e.g. _Functions.js_ will have a test file _Functions.spec.js_.
Tests will be available at _http://localhost:8080/test/test.html_.
### Configuration

@@ -131,0 +180,0 @@

@@ -1,19 +0,21 @@

const path = require('path');
const merge = require('webpack-merge');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpackConfig = require('./webpack.config');
const path = require( "path" );
const merge = require( "webpack-merge" );
const CleanWebpackPlugin = require( "clean-webpack-plugin" );
const webpackConfig = require( "./webpack.config" );
const OUTPUT_FOLDER = "dist";
module.exports = merge( webpackConfig, {
devtool: 'source-map',
devtool: "source-map",
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].min.js'
path : path.join( __dirname, OUTPUT_FOLDER ),
filename : "[name].min.js"
},
plugins: [
new CleanWebpackPlugin(['dist'])
new CleanWebpackPlugin([ OUTPUT_FOLDER ])
]
});

@@ -1,13 +0,33 @@

const merge = require('webpack-merge');
const webpackConfig = require('./webpack.config');
const path = require( "path" );
const webpack = require( "webpack" );
const merge = require( "webpack-merge" );
const HtmlWebpackPlugin = require( "html-webpack-plugin" );
const webpackConfig = require( "./webpack.config" );
const DEMO_FOLDER = path.join( __dirname, "demo" );
module.exports = merge( webpackConfig, {
devtool: 'eval',
entry: {
sia: `${DEMO_FOLDER}/index.js`
},
devtool: "eval",
output: {
pathinfo : true,
publicPath: '/',
filename : '[name].js'
}
publicPath: "/",
filename : "[name].js"
},
plugins: [
new webpack.DefinePlugin({
IS_DEV: true
}),
new HtmlWebpackPlugin({
template : `${DEMO_FOLDER}/index.ejs`,
title : "dev"
})
],
});

@@ -1,11 +0,7 @@

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require( "path" );
const webpack = require( "webpack" );
// Is the current build a development build
const IS_DEV = (process.env.NODE_ENV === 'dev');
const dirNode = "node_modules";
const dirApp = path.join( __dirname, "src" );
const dirNode = 'node_modules';
const dirApp = path.join(__dirname, 'src');
/**

@@ -16,3 +12,3 @@ * Webpack Configuration

entry: {
sia: path.join(dirApp, 'index')
sia: "./index"
},

@@ -25,12 +21,2 @@ resolve: {

},
plugins: [
new webpack.DefinePlugin({
IS_DEV: IS_DEV
}),
new HtmlWebpackPlugin({
template: path.join(__dirname, 'index.ejs'),
title: "dev"
})
],
module: {

@@ -41,3 +27,3 @@ rules: [

test: /\.js$/,
loader: 'babel-loader',
loader: "babel-loader",
exclude: /(node_modules)/,

@@ -44,0 +30,0 @@ options: {

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