{"id":15747323,"url":"https://github.com/igorski/soundcloud-iframe-analytics","last_synced_at":"2026-05-15T01:43:11.149Z","repository":{"id":57366444,"uuid":"137175694","full_name":"igorski/soundcloud-iframe-analytics","owner":"igorski","description":"Easily tracks visitor interaction on embedded SoundCloud content in Google Analytics","archived":false,"fork":false,"pushed_at":"2022-04-14T19:06:05.000Z","size":86,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-17T20:00:54.617Z","etag":null,"topics":["analytics","behaviour","embed","soundcloud","tracking","widget"],"latest_commit_sha":null,"homepage":"https://www.igorski.nl/opensource/soundcloud-iframe-analytics","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/igorski.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-06-13T07:00:58.000Z","updated_at":"2022-02-15T21:30:42.000Z","dependencies_parsed_at":"2022-08-23T20:10:43.026Z","dependency_job_id":null,"html_url":"https://github.com/igorski/soundcloud-iframe-analytics","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/igorski/soundcloud-iframe-analytics","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorski%2Fsoundcloud-iframe-analytics","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorski%2Fsoundcloud-iframe-analytics/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorski%2Fsoundcloud-iframe-analytics/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorski%2Fsoundcloud-iframe-analytics/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/igorski","download_url":"https://codeload.github.com/igorski/soundcloud-iframe-analytics/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorski%2Fsoundcloud-iframe-analytics/sbom","scorecard":{"id":482788,"data":{"date":"2025-08-11","repo":{"name":"github.com/igorski/soundcloud-iframe-analytics","commit":"348a53d1b8808ebb58885679c74916c92f40fc9b"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/21 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-19T17:02:17.742Z","repository_id":57366444,"created_at":"2025-08-19T17:02:17.742Z","updated_at":"2025-08-19T17:02:17.742Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33050704,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-13T13:14:54.681Z","status":"online","status_checked_at":"2026-05-14T02:00:06.663Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["analytics","behaviour","embed","soundcloud","tracking","widget"],"created_at":"2024-10-04T05:04:58.602Z","updated_at":"2026-05-15T01:43:11.126Z","avatar_url":"https://github.com/igorski.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SoundCloud iframe Analytics\n\nSoundCloud Iframe Analytics (SIA) is a minimal library that attaches Google Analytics event tracking\nto user interactions performed on SoundCloud iframes embedded within your HTML page, both on single\ntracks as well as full playlists.\n\nThis allows you to track user behaviour as well as have the events act as beacons to\nmore accurately see page session duration. It also helps you in finding out how popular\nsome of your tracks are ;)\n\nMultiple versions of the Google Analytics tracker are supported, namely:\n\n* Global Site Tag (gtag)\n* analytics.js (ga)\n* the legacy tracker (_gaq)\n\nSee the library in action [here](http://rawgit.com/igorski/soundcloud-iframe-analytics/master/dist/index.html).\n\n## Installation\n\nYou can install this repository as a node module using npm:\n\n```\nnpm install soundcloud-iframe-analytics --save-dev\n```\n\n## How to integrate within your application\n\nFirst, embed the Analytics tracking code as provided by Google into your HTML template(s).\n\nThen, add a SoundCloud iframe embed similar to the below:\n\n```html\n    \u003ciframe\n        width=\"100%\" height=\"300\"\n        scrolling=\"no\" frameborder=\"no\"\n        src=\"https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/playlists/{STRING_ID}\u0026amp;color=%23ff5500\u0026amp;auto_play=false\u0026amp;hide_related=false\u0026amp;show_comments=true\u0026amp;show_user=true\u0026amp;show_reposts=false\u0026amp;show_teaser=true\"\u003e\n    \u003c/iframe\u003e\n```\n\nBasically, you embed the SoundCloud iframes according to the embed code provided by SoundCloud.\nYou do not need to make any changes to the generated markup.\n\n### The easy way : automatically attach tracking to static HTML pages\n\nWhen your HTML pages are static / contain the iframe content upon delivery, you can\neasily attach the Analytics tracking by adding the following snippet to your JavaScript code:\n\n```js\nimport { init } from \"soundcloud-iframe-analytics\";\n\nasync function readyHandler() {\n    document.removeEventListener( \"DOMContentLoaded\", readyHandler );\n    const embeds = await init();\n}\ndocument.addEventListener( \"DOMContentLoaded\", readyHandler );\n```\n\nThe above will run once when the document finishes loading. It will then scan the document for\niframes with SoundCloud content. When found, the SoundCloud player API is loaded asynchronously and\nsubsequently the playback listeners will be added.\n\nThe returned value is a list of successfully bound listeners for each iframe, where each value is\nwrapped inside an object like so:\n\n```js\n{\n    element : HTMLIFrameElement,\n    widget  : SC.Widget,\n    dispose : Function\n}\n```\n\nIn case you are wondering what those are good for, it's good to know that if your SoundCloud\ncontent remains on the page throughout its lifetime, you can safely ignore these. But if you\nare curious, you are likely someone who is looking for...\n\n### The \"I want full control\" way\n\nIn case your page is an SPA that injects/removes SoundCloud iframes at runtime, you\nneed to keep track of additionally added iframes _after_ the document has finished loading.\nYou probably also want to clean up after yourself when you no longer need these iframes.\n\nYou can attach Analytics triggers to injected iframes by passing their reference to the\n_attachSoundCloudAnalytics()_-method. Your pseudo code would look like:\n\n```js\nimport { init, attachSoundCloudAnalytics } from \"soundcloud-iframe-analytics\";\n\nasync function executedOnce() {\n    // passing true guarantees the SoundCloud player API is loaded\n    // regardless of iframes being present at the moment of initialization\n    await init( true );\n}\n\nfunction executeAfterNewIframeIsInjected( iframeReference ) {\n    const result = attachSoundCloudAnalytics( iframeReference );\n    if ( result !== null ) {\n        // SoundCloud Analytics attached successfully\n        // invoke dispose() when the iframe is no longer needed / removed from page\n        const { element, widget, dispose } = result;\n    }\n}\n```\n\nAnd Bob's your uncle. SIA will automatically detect whether the same iframe is\npassed for attachment of Analytics events and will deduplicate everything accordingly.\n\n## Event message format\n\nThe message format for the tracked events is:\n\n * **Category:** SoundCloud\n * **Action:** See list below\n * **Label:** Title of the SoundCloud track\n\nThe tracked actions are:\n\n * _Playback started_\n * _Playback paused_\n * _Playback resumed_\n * _Playback scrubbed_\n * _Progress (num)_\n * _Progress (num) with scrubbing_\n * _Played in full_\n * _Played in full with scrubbing_\n\nWhere:\n\n* _starts_ are counted only once per track (unless it has finished playback, after which we can treat\nit as a new play).\n* _scrubbed_ and _with scrubbing_ indicates that the user has dragged the playback to a different point in the track and thus\nmight have skipped sections. You can use this to determine engagement. _Playback scrubbed_ is tracked only\nonce (unless track has finished playback and is restarted).\n* _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\n\n## Development\n\n### Setup\n\nInstall dependencies as usual:\n\n```\nnpm install\n```\n\n### Local development\n\nLaunching a local server (_webpack-dev-server_) with livereload and\nautomatic recompilation on changes. Server will be available at\n_http://localhost:8080_\n\n```\nnpm run dev\n```\n\n### Creating a production build\n\n```\nnpm run build\n```\n\nBuild output will be stored in _./dist_-folder.\n\n### Unit testing\n\nUnit tests are run via Jest, which is installed as a dependency.\nYou can run the tests by using:\n\n```\nnpm test\n```\n\nUnit tests go in the _./test_-folder. The file name for a unit test must\nbe equal to the file it is testing, but contain the suffix \".spec.js\",\ne.g. _Functions.js_ will have a test file _Functions.spec.js_.\n\n### Configuration\n\nConfigurations for all target environments are in the root of the\nrepository in the _webpack.config.{TARGET}.js_ files.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figorski%2Fsoundcloud-iframe-analytics","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Figorski%2Fsoundcloud-iframe-analytics","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figorski%2Fsoundcloud-iframe-analytics/lists"}