{"id":13516457,"url":"https://github.com/hueitan/javascript-sdk-design","last_synced_at":"2025-08-08T07:12:50.631Z","repository":{"id":30910939,"uuid":"34468774","full_name":"hueitan/javascript-sdk-design","owner":"hueitan","description":"JavaScript SDK Design Guide extracted from work and personal experience","archived":false,"fork":false,"pushed_at":"2024-07-10T07:16:11.000Z","size":342,"stargazers_count":1436,"open_issues_count":2,"forks_count":179,"subscribers_count":44,"default_branch":"master","last_synced_at":"2025-07-29T12:38:36.327Z","etag":null,"topics":["design-guideline","design-principle","document","javascript","javascript-sdk","sdk"],"latest_commit_sha":null,"homepage":"https://sdk-design.js.org/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hueitan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-04-23T16:42:12.000Z","updated_at":"2025-07-27T00:50:12.000Z","dependencies_parsed_at":"2024-08-03T13:16:27.704Z","dependency_job_id":null,"html_url":"https://github.com/hueitan/javascript-sdk-design","commit_stats":null,"previous_names":["huei90/javascript-sdk-design"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/hueitan/javascript-sdk-design","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hueitan%2Fjavascript-sdk-design","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hueitan%2Fjavascript-sdk-design/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hueitan%2Fjavascript-sdk-design/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hueitan%2Fjavascript-sdk-design/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hueitan","download_url":"https://codeload.github.com/hueitan/javascript-sdk-design/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hueitan%2Fjavascript-sdk-design/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268788735,"owners_count":24307676,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-04T02:00:09.867Z","response_time":79,"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":["design-guideline","design-principle","document","javascript","javascript-sdk","sdk"],"created_at":"2024-08-01T05:01:22.434Z","updated_at":"2025-08-08T07:12:50.583Z","avatar_url":"https://github.com/hueitan.png","language":"JavaScript","funding_links":[],"categories":["Technical","Programming Languages","📚 Books","JavaScript"],"sub_categories":["ramanihiteshc@gmail.com","JavaScript"],"readme":"# JavaScript SDK Design Guide \n[![All Contributors](https://img.shields.io/badge/all_contributors-3-orange.svg?style=flat-square)](#contributors-)\n\n## Introduction\n\nThis guide provides an introduction to develop a [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript) SDK.\n\n\u003e The best one sentence to describe an SDK is: _\"The SDK is the connection bridging the gap between users and the (browser) machine.\"_\n\n\nBy using this guide, the SDK will be able to run in browsers, desktop, mobile web and various other platforms capable of running JavaScript. \n\nThe target audience of this writeup excludes **non-browser environments** such as hardware, embedded and Node.js.\n\n\u003e Suggest improvements by [editing](https://github.com/hueitan/JavaScript-sdk-design/edit/master/README.md), or drop suggestions on the [issue list](https://github.com/hueitan/JavaScript-sdk-design/issues). I owe you a beer :beers:\n\n\u003cp align=\"right\"\u003e\n\u003ci\u003eREAD IT\u003c/i\u003e\n\u003ca href=\"http://sdk-design.js.org\" target=\"_blank\"\u003eONLINE\u003c/a\u003e \u003cbr/\u003e\n\u003c/p\u003e\n\n\u003c!--\u003chr/\u003e--\u003e\n\u003c!--\u003cp align=\"center\"\u003e--\u003e\n\u003c!--\u003ca href=\"http://ctt.ec/GyjRN\" title=\"Click to Tweet\"\u003eClick to Tweet\u003c/a\u003e--\u003e\n\u003c!--\u003c/p\u003e--\u003e\n\u003chr/\u003e\n\n## Content\n\n* [What is an SDK](#what-is-an-sdk)\n* [Design Philosophy](#design-philosophy)\n* [Scope](#scope)\n* [Include the SDK](#include-the-sdk)\n  * [Asynchronous Syntax](#asynchronous-syntax)\n  * [Traditional Syntax](#traditional-syntax)\n  * [Comparison](#comparison)\n  * [Problem of Asynchronous](#problem-of-asynchronous)\n  * [Others](#others)\n* [SDK Versioning](#sdk-versioning)\n* [Changelog Document](#changelog-document)\n* [Namespace](#namespace)\n* [Storage Mechanism](#storage-mechanism)\n  * [Cookie](#cookie)\n    * [Check Cookie Writable](#check-cookie-writable)\n    * [Check Third-Party Cookie Writable](#check-third-party-cookie-writable)\n    * [Write Read Remove Cookie Code](#writereadremove-cookie-code)\n  * [Session](#session)\n  * [LocalStorage](#localstorage)\n    * [Check LocalStorage Writable](#check-localstorage-writable)\n  * [Session Storage](#session-storage)\n    * [Check SessionStorage Writable](#check-sessionstorage-writable)\n* [Event](#event)\n  * [Document Ready](#document-ready)\n  * [Message Event](#message-event)\n  * [Orientation Change](#orientation-change)\n  * [Disable Scroll](#disable-scroll)\n* [Request](#request)\n  * [Image Beacon](#image-beacon)\n  * [Single Post](#single-post)\n  * [Multiple Posts](#multiple-posts)\n  * [Iframe](#iframe)\n  * [Script jsonp](#script-jsonp)\n  * [Navigator.sendBeacon()](#navigatorsendbeacon)\n  * [XMLHttpRequest](#xmlhttprequest)\n  * [Fragment Identifier](#fragment-identifier)\n  * [Maximum Number of Connections](#maximum-number-of-connections)\n* [Component of URI](#component-of-uri)\n  * [Parsing URI](#parsing-uri)\n* [Debugging](#debugging)\n  * [Simulating Multiple Domains](#simulating-multiple-domains)\n  * [Developer Tools](#developer-tools)\n  * [Simulate a slower network connection](#simulate-a-slower-network-connection)\n  * [Console Logs](#console-logs)\n  * [Debugging Proxy](#debugging-proxy)\n  * [BrowserSync](#browsersync)\n  * [Debugging Node.js Apps](#debugging-nodejs-apps)\n* [Tips and Tricks](#tips-and-tricks)\n  * [Piggyback](#piggyback)\n  * [Page Visibility API](#page-visibility-api)\n  * [Document Referrer](#document-referrer)\n  * [Console Logs Polyfill](#console-logs-polyfill)\n  * [EncodeURI or EncodeURIComponent](#encodeuri-or-encodeuricomponent)\n  * [YOU MIGHT NOT NEED JQUERY](#you-might-not-need-jquery)\n  * [You Don't Need jQuery](#you-dont-need-jquery)\n  * [Load Script with Callback](#load-script-with-callback)\n  * [Once Function](#once-function)\n  * [Pixel Ratio Density](#pixel-ratio-density)\n  * [Get Style Value](#get-style-value)\n  * [Check if Element in Viewport](#check-if-element-in-viewport)\n  * [Check if Element is Visible](#check-if-element-is-visible)\n  * [Get Viewport Size](#get-viewport-size)\n  * [User Tracking](#user-tracking)\n  * [Opt Out](#opt-out)\n* [WTF](#wtf)\n  * [Misspelling Of Referrer](#misspelling-of-referrer)\n  * [CSS Flexible Box Layout Module](#css-flexible-box-layout-module)\n* [Template](#template)\n* [Book to Read](#booksnice-to-reads)\n* [Contributors](#contributors-)\n\n## What is an SDK\n\nThis question is pretty ubiquitous, but here it is again.\n\n\"Short for **software development kit**, a programming package that enables a programmer to develop applications for a specific platform. Typically an SDK includes one or more APIs, programming tools, and documentation.\" - _[webopedia](http://www.webopedia.com/TERM/S/SDK.html)_\n\n## Design Philosophy\n\nDepending on the purpose of SDK's service and usage — common shared traits are, but not limited to be **native**, **short**, **fast**, **clean**, **readable** and **testable**.\n\nThe widely adopted good practice, is to write SDK with vanilla JavaScript. \nLanguages compiling to JavaScript such as LiveScript, CoffeeScript, TypeScript and others are **not** recommended.\n\nIt is also recommended **not** to use libraries such as jQuery in SDK development. \nThe exception is of course when it is really important. There are also other jQuery-like libraries, zepto.js _etc_ to choose from, for the DOM manipulation purposes.\n\nIn event of HTTP [ajax request](#request) requirements — there are native equivalent such as `window.fetch`. It is light-weight, supported in ever growing platforms. \n\n[Backward compatibility](https://en.wikipedia.org/wiki/Backward_compatibility#In_software) is paramount. Every new  SDK version released should be enabled with  support of previous older versions. Likewise, current version should be designed to support future SDK versions. This is referred to as Forward compatibility.\n\nMoreover, a good **Documentation**, well commented code, a healthy unit test coverage, as well as end-to-end (user) scenario are key to the success of SDK.\n\n## Scope\n\n*Based on the book [Third-Party JavaScript](http://thirdpartyjs.com)*\n\nThree use cases worth considering while designing a JavaScript SDK:\n\n1. [Embedded widgets](./SCOPE.md#embedded-widgets) - Small interactive applications embedded on the publisher's web page (Disqus, Google Maps, Facebook Widget)\n2. [Analytics and metrics](./SCOPE.md#analytics-and-metrics) - For gathering intelligence about visitors and how they interact with the publisher's website (GA, Flurry, Mixpanel)\n3. [Web service API wrappers](./SCOPE.md#web-service-api-wrappers) - For developing client-side applications that communicate with external web services. (Facebook Graph API)\n\n\u003e [Suggest a case](https://github.com/hueitan/JavaScript-sdk-design/edit/master/README.md) in which the use of an SDK in JavaScript environment is deemed important.\n\n## Include the SDK\n\nTo include the SDK in a user-facing environment, It is a good practice to use **Asynchronous Syntax** to load the scripts.\n\nThis helps to optimize the user experience on the website that are using the SDK.\nThis approach reduces chances of the SDK library interfering with the hosting website.\n\n### Asynchronous Syntax\n\n```html\n\u003cscript\u003e\n  (function () {\n    var s = document.createElement('script');\n    s.type = 'text/javascript';\n    s.async = true;\n    s.src = 'http://\u003cDOMAIN\u003e.com/sdk.js';\n    var x = document.getElementsByTagName('script')[0];\n    x.parentNode.insertBefore(s, x);\n  })();\n\u003c/script\u003e\n```\n\nThe `async` syntax is used when targetting modern browsers.\n\n```html\n\u003cscript async src=\"http://\u003cDOMAIN\u003e.com/sdk.js\"\u003e\u003c/script\u003e\n```\n\n### Traditional Syntax\n\n```html\n\u003cscript type=\"text/javascript\" src=\"http://\u003cDOMAIN\u003e.com/sdk.js\"\u003e\u003c/script\u003e\n```\n\n### Comparison\n\nHere's the simple graph to show the difference between Asynchronous and Traditional Syntax.\n\nAsynchronous:\n\n``` \n |----A-----|\n    |-----B-----------|\n        |-------C------|\n```\n\nSynchronous:\n\n```\n  |----A-----||-----B-----------||-------C------|\n```\n\nAsynchronous and deferred JavaScript execution explained\n\n\u003cimg src=\"http://peter.sh/wp-content/uploads/2010/09/execution2.jpg\"/\u003e\n\n\n\n\u003e _https://developers.google.com/speed/docs/insights/BlockingJS_ \u003cbr/\u003e\n\u003e It is good practice to avoid, or minimize, the use of blocking JavaScript, especially external scripts that must be fetched before they can be executed. Scripts that are necessary to render page content can be inlined to avoid extra network requests, however the inlined content needs to be small and must execute quickly (non-blocking fashion) to deliver good performance. Scripts that are not critical to initial render should be made asynchronous or deferred until after the first render.\n\n### Problem of Asynchronous\n\nWhen using an Asynchronous approach, It is ill-advised to execute SDK initialization functions before all libraries are loaded, parsed and executed in the hosting page.\n\nConsider the following snippet as a visual example to the previous statement:\n\n```javascript\n\u003cscript\u003e\n  (function () {\n    var s = document.createElement('script');\n    s.type = 'text/javascript';\n    s.async = true;\n    s.src = 'http://\u003cDOMAIN\u003e.com/sdk.js';\n    var x = document.getElementsByTagName('script')[0];\n    x.parentNode.insertBefore(s, x);\n  })();\n\n  // execute your script immediately here\n  SDKName('some arguments');\n\u003c/script\u003e\n```\n\nThe end result of such initialization will lead to bugs. \nThe `SDKName()` function, undefined at this point, executes before it becomes available in the environment's global variable. The script is not loaded yet.\n\nTo make it work, some tricks are necessary to make sure the script executes successfully. The event will (need to) be stored in the `SDKName.q` queue array. The SDK should be able to handle and execute the `SDKName.q` event and initialize the `SDKName` namespace.\n\nThe following snippet depicts the statement in previous paragraph.\n\n```javascript\n\u003cscript\u003e\n  (function () {\n    // add a queue event here\n    SDKName = SDKName || function () {\n      (SDKName.q = SDKName.q || []).push(arguments);\n    };\n    var s = document.createElement('script');\n    s.type = 'text/javascript';\n    s.async = true;\n    s.src = 'http://\u003cDOMAIN\u003e.com/sdk.js';\n    var x = document.getElementsByTagName('script')[0];\n    x.parentNode.insertBefore(s, x);\n  })();\n\n  // execute your script immediately here\n  SDKName('some arguments');\n\u003c/script\u003e\n```\n\n**Or** using `[].push`\n\n```js\n\u003cscript\u003e\n  (function () {\n    // add a queue event here\n    SDKName = window.SDKName || (window.SDKName = []);\n    var s = document.createElement('script');\n    s.type = 'text/javascript';\n    s.async = true;\n    s.src = 'http://\u003cDOMAIN\u003e.com/sdk.js';\n    var x = document.getElementsByTagName('script')[0];\n    x.parentNode.insertBefore(s, x);\n  })();\n\n  // execute your script immediately here\n  SDKName.push(['some arguments']);\n\u003c/script\u003e\n```\n\n### Others\n\nThere are other different ways to include a script\n\n#### Import in ES2015\n\n```javascript\n  import \"your-sdk\";\n```\n\n#### Modular include a Script\n\nThere is full source code — and this awesome tutorial _\"[Loading JavaScript Modules](https://libraryinstitute.wordpress.com/2010/12/01/loading-javascript-modules/)\"_ may help for in-depth understanding of concepts discussed above.\n\n```js\nmodule('sdk.js',['sdk-track.js', 'sdk-beacon.js'],function(track, beacon) {\n  // sdk definitions, split into local and global/exported definitions\n  // local definitions\n  // exports\n});\n\n// you should contain this \"module\" method\n(function () {\n\n  var modules = {}; // private record of module data\n\n  // modules are functions with additional information\n  function module(name,imports,mod) {\n\n    // record module information\n    window.console.log('found module '+name);\n    modules[name] = {name:name, imports: imports, mod: mod};\n\n    // trigger loading of import dependencies\n    for (var imp in imports) loadModule(imports[imp]);\n\n    // check whether this was the last module to be loaded\n    // in a given dependency group\n    loadedModule(name);\n  }\n\n  // function loadModule\n  // function loadedModule\n\n  window.module = module;\n})();\n```\n\n## SDK Versioning\n\nIt is not a good practice to use one of the following versioning styles: \n\n  - `brand-v\u003ctimestamp\u003e.js` \n  - `brand-v\u003cdatetime\u003e.js` \n  - `brand-v1-v2.js`,\n\nThe reason is that it becomes confusing to track the lastest version. \nTherefore, previous styling does not help developers who use the SDK.\n\nIt is however a good practice to use [Semantic Versioning](http://semver.org), also known as **SemVer**, when versioning SDKs.\nIt has three main parts, each corresponding to importance of a release: \"MAJOR.MINOR.PATCH\".\nVersion in `v1.0.0` `v1.5.0` `v2.0.0` is easier to trace and track in changelog documentation, for instance.\n\nDepending on service design, some of the ways SDK can be distributed (or tracked) by version are the following:\n\n - Using Query String path — `http://\u003cDOMAIN\u003e.com/sdk.js?v=1.0.0`\n - Using the Folder Naming — `http://\u003cDOMAIN\u003e.com/v1.0.0/sdk.js`\n - Using hostname (subdomain) — `http://v1.\u003cDOMAIN\u003e.com/sdk.js`\n\nDepending on Use Case, there are other environment dependent forms that are commonly advised to use:  \n\n - In `stable` version `http://\u003cDOMAIN\u003e.com/sdk-stable.js`  \n - In `unstable` version `http://\u003cDOMAIN\u003e.com/sdk-unstable.js` \n - In `alpha` version `http://\u003cDOMAIN\u003e.com/sdk-alpha.js` \n - In `latest` version `http://\u003cDOMAIN\u003e.com/sdk-latest.js` \n - In `experimental` version `http://\u003cDOMAIN\u003e.com/sdk-experimental.js`\n\n\u003e Reading suggestion: _*[Why use SemVer?](http://blog.npmjs.org/post/162134793605/why-use-semver)*_ on `npm` blog.\n\n## Changelog Document\n\nIt's hard to notice when an SDK has updates (or is upgraded) when no announcement has been issued.\nIt's good practice to write a Changelog to document major, minor and even bug-fix changes.\nTracking changes in SDK APIs deliver good developer experience. - _[Keep a Changelog](http://keepachangelog.com) ([Github Repo](https://github.com/olivierlacan/keep-a-changelog))_\n\nEach version should have:\n\n```\n[Added] for new features.\n[Changed] for changes in existing functionality.\n[Deprecated] for soon-to-be removed features.\n[Removed] for now removed features.\n[Fixed] for any bug fixes.\n[Security] in case of vulnerabilities.\n```\n\nIn addition, [commit-message-emoji](https://github.com/dannyfritz/commit-message-emoji) uses an emoji to explain the commit's changes itself. Find the best suitable format or [changelog generator tool](https://github.com/topics/changelog) for your project.\n\n## Namespace\n\nTo avoid collision with other libraries, it is better to define no more than one global SDK namespace.\nThe naming should also avoid using the commonly used words and catch-phrases as namespaces.\n\nAs a quick example, SDK playground can well use `(function () { ... })()` or ES6 Blocks `{ ... }` to wrap all sources.\n\nThis is an increasingly common practice found in many popular JavaScript libraries such as (jQuery, Node.js, etc.). This technique creates a closure around the entire contents of the file which, perhaps most importantly, creates a private namespace and thereby helps avoid potential name clashes between different JavaScript modules and libraries. [#](http://www.toptal.com/javascript/interview-questions)\n\nTo avoid **namespace collision**\n\nFrom Google Analytics, define the namespace by changing the value `ga`\n\n```js\n(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\nm=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n})(window,document,'script','//www.google-analytics.com/analytics.js','ga');\n```\n\nFrom [OpenX experience](http://docs.openx.com/ad_server/adtags_namespace.html), support a parameter to request the namespace.\n\n```html\n\u003cscript src=\"http://your_domain/sdk?namespace=yourcompany\"\u003e\u003c/script\u003e\n```\n\n## Storage Mechanism\n\n### Cookie\n\nThe domain scope of using cookies is quite complex while involving the `subdomain` and `path`.\n\nFor `path=/`,\nthere is a cookie part `first=value1` in domain `http://github.com`,\nand another cookie `second=value2` in domain `http://sub.github.com`\n\n|               | http://github.com | http://sub.github.com |\n|:-------------:|:-----------------:|:---------------------:|\n| first=value1  |         ✓         |           ✓           |\n| second=value2 |         ✘         |           ✓           |\n\nThere is a cookie `first=value1` in domain `http://github.com`,\ncookie `second=value2` in domain path `http://github.com/path1`\nand cookie `third=value3` in domain `http://sub.github.com`,\n\n\n|               | http://github.com | http://github.com/path1 | http://sub.github.com |\n|:-------------:|:-----------------:|:-----------------------:|:---------------------:|\n| first=value1  |         ✓         |            ✓            |           ✓           |\n| second=value2 |         ✘         |            ✓            |           ✘           |\n| third=value3  |         ✘         |            ✘            |           ✓           |\n\n#### Check Cookie Writable\n\nGiven a domain (Default as current hostname), check whether the cookie is writable.\n\n```js\nvar checkCookieWritable = function(domain) {\n    try {\n        // Create cookie\n        document.cookie = 'cookietest=1' + (domain ? '; domain=' + domain : '');\n        var ret = document.cookie.indexOf('cookietest=') != -1;\n        // Delete cookie\n        document.cookie = 'cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT' + (domain ? '; domain=' + domain : '');\n        return ret;\n    } catch (e) {\n        return false;\n    }\n};\n```\n\n#### Check Third-Party Cookie Writable\n\nIt's impossible to check only using client-side JavaScript, but a server can help to achieve just that. \n\n#### Write/Read/Remove Cookie Code\n\nCode snippet for write/read/remove cookie script.\n\n```js\nvar cookie = {\n    write: function(name, value, days, domain, path) {\n        var date = new Date();\n        days = days || 730; // two years\n        path = path || '/';\n        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));\n        var expires = '; expires=' + date.toGMTString();\n        var cookieValue = name + '=' + value + expires + '; path=' + path;\n        if (domain) {\n            cookieValue += '; domain=' + domain;\n        }\n        document.cookie = cookieValue;\n    },\n    read: function(name) {\n        var allCookie = '' + document.cookie;\n        var index = allCookie.indexOf(name);\n        if (name === undefined || name === '' || index === -1) return '';\n        var ind1 = allCookie.indexOf(';', index);\n        if (ind1 == -1) ind1 = allCookie.length;\n        return unescape(allCookie.substring(index + name.length + 1, ind1));\n    },\n    remove: function(name) {\n        if (this.read(name)) {\n            this.write(name, '', -1, '/');\n        }\n    }\n};\n```\n### Session\n\nIt's important to know that in JavaScript it is **not possible** to write a Session.\nThat is the server responsibility. The server-side team should implement Session management related Use Cases.\n\nA page session lasts for as long as the browser is open and survives over page reloads and restores. Opening a page in a new tab or window will cause a new session to be initiated.\n\n### LocalStorage\n\nStores data with no expiration date, storage limit is far larger (at least 5MB) and\ninformation is never transferred to the server.\n\nIt's good to know that each localStorage from `http` and `https` in the same domain aren't shared.\nCreating an iframe inside a website and using `postMessage` to pass the value to others. \n\n- [HOW TO?](http://stackoverflow.com/questions/10502469/is-there-any-workaround-to-make-use-of-html5-localstorage-on-both-http-and-https)\n\n#### Check LocalStorage Writable\n\nwindow.localStorage is not supported by all browsers, the SDK should check if it's available before using it.\n\n```js\nvar testCanLocalStorage = function() {\n   var mod = 'modernizr';\n   try {\n       localStorage.setItem(mod, mod);\n       localStorage.removeItem(mod);\n       return true;\n   } catch (e) {\n       return false;\n   }\n};\n```\n\n### Session Storage\n\nStores data for one session (data is lost when the tab is closed).\n\n### Check SessionStorage Writable\n\n```js\nvar checkCanSessionStorage = function() {\n  var mod = 'modernizr';\n  try {\n    sessionStorage.setItem(mod, mod);\n    sessionStorage.removeItem(mod);\n    return true;\n  } catch (e) {\n    return false;\n  }\n}\n```\n\n## Event\n\nIn client browser, there are events `load` `unload` `on` `off` `bind` .... Here's some [polyfills](https://remysharp.com/2010/10/08/what-is-a-polyfill) for you to handle all different platforms.\n\n### Document Ready\n\nPlease do make sure that the entire page is finished loading (ready) before starting execution of the SDK functions.\n\n```js\n// handle IE8+\nfunction ready (fn) {\n    if (document.readyState != 'loading') {\n        fn();\n    } else if (window.addEventListener) {\n        // window.addEventListener('load', fn);\n        window.addEventListener('DOMContentLoaded', fn);\n    } else {\n        window.attachEvent('onreadystatechange', function() {\n            if (document.readyState != 'loading')\n                fn();\n            });\n    }\n}\n```\n\n\u003e **DOMContentLoaded** -  fired when the document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading\n\n\u003e **load** event can be used to detect a fully-loaded page\n\n\u003e Information from JS Tip - https://github.com/loverajoel/jstips/blob/master/_posts/en/javascript/2016-02-15-detect-document-ready-in-pure-js.md\n\n\u003e [element-ready](https://github.com/sindresorhus/element-ready) from [sindresorhus](https://github.com/sindresorhus)\n\n### Message Event\n\nIt's about the cross-origin communication between iframe and window, read the [API documentation](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage).\n\n```js\n// in the iframe\nparent.postMessage(\"Hello\"); // string\n\n// ==========================================\n\n// in the iframe's parent\n// Create IE + others compatible event handler\nvar eventMethod = window.addEventListener ? \"addEventListener\" : \"attachEvent\";\nvar eventer = window[eventMethod];\nvar messageEvent = eventMethod == \"attachEvent\" ? \"onmessage\" : \"message\";\n\n// Listen to message from child window\neventer(messageEvent,function(e) {\n  // e.origin , check the message origin\n  console.log('parent received message!:  ',e.data);\n},false);\n```\n\nThe Post message data should be **String**, for more advanced use in JSON, use **JSON String**. Although the modern browsers do support [Structured Clone Algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) on the parameter, not all browsers do.\n\n### Orientation Change\n\nDetect device orientation change\n\n```js\nwindow.addEventListener('orientationchange', fn);\n```\n\nGet Orientation Rotate Degree\n\n```js\nwindow.orientation; // =\u003e 90, -90, 0\n```\n\nScreen portrait-primary, portrait-secondary, landscape-primary, landscape-secondary (Experimental)\n\n```js\n// https://developer.mozilla.org/en-US/docs/Web/API/Screen/orientation\nvar orientation = screen.orientation || screen.mozOrientation || screen.msOrientation;\n```\n\n### Disable Scroll\n\nIn web page, use CSS style `overflow: hidden`, in some mobile webs, this CSS doesn't work, use JavaScript event.\n\n```js\ndocument.addEventListener('touchstart', function(e){ e.preventDefault(); });\n// or\ndocument.body.addEventListener('touchstart', function(e){ e.preventDefault(); });\n// use move if you need some touch event\ndocument.addEventListener('touchmove', function(e){ e.preventDefault(); });\n// target modern browser\ndocument.addEventListener('touchmove', function(e){ e.preventDefault(); }, { passive: false });\n```\n\n## Request\n\nThe communication between our SDK and Server is using Ajax Request. \nMost common use cases leverage jQuery's ajax http request to communicate with the Server. The good news is that there is an even better solution to achieve that.\n\n### Image Beacon\n\nUsing the Image Beacon to ask the browser to perform a GET method `request` to get an Image.\n\n*Ones should always remember to add timestamp (Cache Buster) to prevent caching in browser.*\n\n```js\n(new Image()).src = 'http://\u003cDOMAIN\u003e.com/collect?id=1111';\n```\n\nSome notice for GET Query String, there is the limit of length which is 2048 (Basically it depends on different browsers and server). The following trick helps to handle the case of exceeded length limit.\n\n```js\nif (length \u003e 2048) {\n    // do Multiple Post (form)\n} else {\n    // do Image Beacon\n}\n```\n\nThere are well-known problems using `encodeURI` or `encodeURIComponent`. However, it is better to understand how these two approaches work. [Reading details below](#encodeuri-or-encodeuricomponent).\n\nFor the image load **success/error callback**\n\n```js\nvar img = new Image();\nimg.src = 'http://\u003cDOMAIN\u003e.com/collect?id=1111';\nimg.onload = successCallback;\nimg.onerror = errorCallback;\n```\n\n### Single Post\n\nit is possible to use the native form element POST method to send a key value.\n\n```js\nvar form = document.createElement('form');\nvar input = document.createElement('input');\n\nform.style.display = 'none';\nform.setAttribute('method', 'POST');\nform.setAttribute('action', 'http://\u003cDOMAIN\u003e.com/track');\n\ninput.name = 'username';\ninput.value = 'attacker';\n\nform.appendChild(input);\ndocument.getElementsByTagName('body')[0].appendChild(form);\n\nform.submit();\n```\n\n### Multiple Posts\n\nThe Service is often complex, especially when needing to send more data through a POST method.\n\n```js\nfunction requestWithoutAjax( url, params, method ){\n\n    params = params || {};\n    method = method || \"post\";\n\n    // function to remove the iframe\n    var removeIframe = function( iframe ){\n        iframe.parentElement.removeChild(iframe);\n    };\n\n    // make a iframe...\n    var iframe = document.createElement('iframe');\n    iframe.style.display = 'none';\n\n    iframe.onload = function(){\n        var iframeDoc = this.contentWindow.document;\n\n        // Make a invisible form\n        var form = iframeDoc.createElement('form');\n        form.method = method;\n        form.action = url;\n        iframeDoc.body.appendChild(form);\n\n        // pass the parameters\n        for( var name in params ){\n            var input = iframeDoc.createElement('input');\n            input.type = 'hidden';\n            input.name = name;\n            input.value = params[name];\n            form.appendChild(input);\n        }\n\n        form.submit();\n        // remove the iframe\n        setTimeout( function(){\n            removeIframe(iframe);\n        }, 500);\n    };\n\n    document.body.appendChild(iframe);\n}\n```\n```js\nrequestWithoutAjax('url/to', { id: 2, price: 2.5, lastname: 'Gamez'});\n```\n\n### Iframe\n\nIframe embedded in html can always be used to cover the use case of generating content within the page.\n\n```js\nvar iframe = document.createElement('iframe');\nvar body = document.getElementsByTagName('body')[0];\n\niframe.style.display = 'none';\niframe.src = 'http://\u003cDOMAIN\u003e.com/page';\niframe.onreadystatechange = function () {\n    if (iframe.readyState !== 'complete') {\n        return;\n    }\n};\niframe.onload = loadCallback;\n\nbody.appendChild(iframe);\n```\n\n**Remove extra margin from INSIDE an iframe**\n\n```html\n\u003ciframe src=\"...\"\n marginwidth=\"0\"\n marginheight=\"0\"\n hspace=\"0\"\n vspace=\"0\"\n frameborder=\"0\"\n scrolling=\"no\"\u003e\u003c/iframe\u003e\n```\n\n**Putting html content into an iframe**\n\n```html\n\u003ciframe id=\"iframe\"\u003e\u003c/iframe\u003e\n\n\u003cscript\u003e\n  var html_string= \"content \u003cscript\u003ealert(location.href);\u003c/script\u003e\";\n  document.getElementById('iframe').src = \"data:text/html;charset=utf-8,\" + escape(html_string);\n  // alert data:text/html;charset=utf-8.....\n  // access cookie get ERROR\n\n  var doc = document.getElementById('iframe').contentWindow.document;\n  doc.open();\n  doc.write('\u003cbody\u003eTest\u003cscript\u003ealert(location.href);\u003c/script\u003e\u003c/body\u003e');\n  doc.close();\n  // alert \"top window url\"\n\n  var iframe = document.createElement('iframe');\n  iframe.src = 'javascript:;\\'' + encodeURI('\u003chtml\u003e\u003cbody\u003e\u003cscript\u003ealert(location.href);\u003c/body\u003e\u003c/html\u003e') + '\\'';\n  // iframe.src = 'javascript:;\"' + encodeURI((html_tag).replace(/\\\"/g, '\\\\\\\"')) + '\"';\n  document.body.appendChild(iframe);\n  // alert \"about:blank\"\n\u003c/script\u003e\n```\n\n### Script jsonp\n\nThis is the case where your server needs to send a JavaScript `response` and let the client browser execute it.\nJust include the JS script link.\n\n```js\n  (function () {\n    var s = document.createElement('script');\n    s.type = 'text/javascript';\n    s.async = true;\n    s.src = '/yourscript?some=parameter\u0026callback=jsonpCallback';\n    var x = document.getElementsByTagName('script')[0];\n    x.parentNode.insertBefore(s, x);\n  })();\n```\n\nTo learn more about jsonp\n\n1. JSONP only works in GET HTTP requests.\n2. JSONP lacks error handling, means you cannot detect cases in response status code 404, 500 and so on.\n3. JSONP requests are always asynchronous.\n4. Beware of CSRF attack.\n5. Cross domain communication. Script response side (server-side) don't need to care about CORS.\n\n### Navigator.sendBeacon()\n\nLook at the [documentation](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon).\n\n\u003e This method addresses the needs of analytics and diagnostics code that typically attempt to send data to a web server prior to the unloading of the document. Sending the data any sooner may result in a missed opportunity to gather data. However, ensuring that the data has been sent during the unloading of a document is something that has traditionally been difficult for developers.\n\nSend POST beacon through the API. It's cool.\n\n```js\nnavigator.sendBeacon(\"/log\", analyticsData);\n```\n\n### XMLHttpRequest\n\nWriting XMLHttpRequest is not a good idea. I assume that you don't want to waste time on battling with IE or other browsers. Here are some polyfills or code you can try:\n\n1. [window.fetch](https://github.com/github/fetch) - A window.fetch JavaScript polyfill. (check also [ky](https://github.com/sindresorhus/ky))\n2. [got](https://github.com/sindresorhus/got) - Simplified HTTP/HTTPS requests\n3. [microjs](http://microjs.com/#ajax) - list of ajax lib\n4. more\n\n### Fragment Identifier\n\nAlso known as hash mark `#`. Remember that requests with hash mark at the end are not passed within http requests.\n\nFor example, you are in the page `http://github.com/awesome#hueitan`\n\n```js\n// Sending a request with a parameter url which contains current url\n(new Image()).src = 'http://yourrequest.com?url=http://github.com/awesome#hueitan';\n\n// actual request will be without #\n(new Image()).src = 'http://yourrequest.com?url=http://github.com/awesome';\n\n// Solution, encodeURIComponent(url):\n(new Image()).src = 'http://yourrequest.com?url=' + encodeURIComponent('http://github.com/awesome#hueitan');\n```\n\n### Maximum Number of Connections\n\nCheck the maximum number of the browser's request connections. [browserscope](http://www.browserscope.org/?category=network\u0026v=top)\n\n\u003ch2 align=\"center\"\u003e\n \u003cimg src=\"https://cloud.githubusercontent.com/assets/2560096/9082891/ac4dc26e-3b99-11e5-8178-606270a801c4.png\" alt=\"max number of connection\"/\u003e\n\u003c/h2\u003e\n\n## Component of URI\n\nIt's important to know if the SDK needs to parse the location url.\n```\n                         authority\n                   __________|_________\n                  /                    \\\n              userinfo                host                          resource\n               __|___                ___|___                 __________|___________\n              /      \\              /       \\               /                      \\\n         username  password     hostname    port     path \u0026 segment      query   fragment\n           __|___   __|__    ______|______   |   __________|_________   ____|____   |\n          /      \\ /     \\  /             \\ / \\ /                    \\ /         \\ / \\\n    foo://username:password@www.example.com:123/hello/world/there.html?name=ferret#foo\n    \\_/                     \\ / \\       \\ /    \\__________/ \\     \\__/\n     |                       |   \\       |           |       \\      |\n  scheme               subdomain  \\     tld      directory    \\   suffix\n                                   \\____/                      \\___/\n                                      |                          |\n                                    domain                   filename\n```\n\n### Parsing URI\n\nHere's a simple way using the native URL() Interface but it's not supported by all browsers.\nIt is also [not a standard yet](https://developer.mozilla.org/en-US/docs/Web/API/Window/URL).\n\n```js\nvar parser = new URL('http://github.com/hueitan');\nparser.hostname; // =\u003e \"github.com\"\n```\n\nThe DOM 's `createElement('a')` can be used in browsers that don't have the `URL()` Interface yet.\n\n```js\nvar parser = document.createElement('a');\nparser.href = \"http://github.com/hueitan\";\nparser.hostname; // =\u003e \"github.com\"\n```\n\n## Debugging\n\n### Simulating Multiple Domains\n\nTo simulate multiple domains, there is no need to register different domain names.\nEditing operating system's hosts file can do the trick.\n\n```shell\n$ sudo vim /etc/hosts\n```\n\nAdd the following entries\n\n```shell\n# refer to localhost\n127.0.0.1 publisher.net\n127.0.0.1 sdk.net\n```\n\nEvery website URL becomes accessible via `http://publisher.net` and `http://sdk.net`\n\n### Developer Tools\n\nBrowsers come with debugging tools specific to every vendor. Obviously, these tools can be used to debug SDK JavaScript code - `Chrome Developer Tools` `Safari Developer Tools` `Firebug`. Developer tools also shortened as DevTools.\n\n\u003e The DevTools provide web developers deep access into the internals of the browser and their web application. Use the DevTools to efficiently track down layout issues, set JavaScript breakpoints, and get insights for code optimization.\n\n### Simulate a slower network connection\n\n\u003e The network connection of the computer that you use to build sites is probably faster than the network connections of the mobile devices of your users. By throttling the page you can get a better idea of how long a page takes to load on a mobile device. --- https://developers.google.com/web/tools/chrome-devtools/network#throttle\n\n![screenshot](https://developers.google.com/web/tools/chrome-devtools/network-performance/imgs/tutorial/throttling.png)\n\n### Console Logs\n\nFor testing expected output text and other general debugging, `Console Logs` can be used through the browser API `console.log()`. There are various typeways to format and output messages. There is more on this discussed at this link: [Console API](https://developer.mozilla.org/en/docs/Web/API/console).\n\n![screen shot 2015-06-15 at 3 50 23 pm](https://cloud.githubusercontent.com/assets/2560096/8155377/411fb24a-1376-11e5-98da-f71f8ed29bcd.png)\n\n### Debugging Proxy\n\nDebugging proxy gives us a hand on testing SDK in development. \nSome of the areas covered are: \n\n- Debugging traffic\n- modify cookies\n- Inspecting headers\n- Verifying the cache\n- Editing http request/response\n- SSL Proxying\n- Debugging Ajax and more.\n\nHere's some software you can try\n- [FiddlerCore](http://www.telerik.com/fiddler/fiddlercore)\n- [Charles](http://www.charlesproxy.com)\n- [Cellist](https://itunes.apple.com/tw/app/cellist-http-debugging-proxy/id897814548?l=zh\u0026mt=12)\n\n### BrowserSync\n\n[BrowserSync](http://www.browsersync.io) makes it easy to tweak and test faster by synchronizing file changes and interactions across multiple devices. It’s wicked-fast and totally free.\n\nIt really helps a lot to test the SDK across mutliple devices. Totally worth a try =)\n\n### Debugging Node.js Apps\n\nTo debug SDK scripts in Chrome Developer Tools. (Node.js v6.3.0+ required)\n\n```shell\n  $ node --inspect-brk [script.js]\n```\n\n- [Official document](https://nodejs.org/en/docs/inspector/)\n- [Paul Irish gave a talk in 15 minutes about how to use --inspect](https://www.youtube.com/watch?v=Xb_0awoShR8)\n\n## Tips and Tricks\n\n### Piggyback\n\nSometimes, including all the SDK source code is not required in some use cases.\nThat is the case of a simple 1x1 pixel request -- For example: make a request when someone lands on thank you (last) page. \nIn such a scenario, the developer may include an image file with a the (url) link, as explained in the following snippet.\n\n```html\n\u003cimg height=\"1\" width=\"1\" alt=\"\" style=\"display:none\" src=\"https://yourUrlLink.com/t?timestamp=1234567890\u0026type=page1\u0026currency=USD\u0026noscript=1\" /\u003e\n```\n\n### Page Visibility API\n\nSometimes, the SDK wants to detect if a user has a particular page in focus. \nThese polyfills  [visibly.js](https://github.com/addyosmani/visibly.js) and [visibilityjs](https://github.com/ai/visibilityjs) may help achieve just that.\n\n### Document Referrer\n\nThe `document.referrer` can be used to get the url of current or previous page. \nIt is however advised to remember that this referrer is \"Browser Referrer\" not the \"Human Known Referrer\". \nThe case where a user clicks the **browser back button**, for example pageA -\u003e pageB -\u003e pageC -\u003e (back button) pageB, current pageB's referrer is pageA, not pageC.\n\n### Console Logs Polyfill\n\nThe following is not a special polyfill. It just makes sure that calling `console.log` API doesn't throw error event to client-side.\n\n```js\nif (typeof console === \"undefined\") {\n    var f = function() {};\n    console = {\n        log: f,\n        debug: f,\n        error: f,\n        info: f\n    };\n}\n```\n\n### EncodeURI or EncodeURIComponent\n\nUnderstand the difference between `escape()` `encodeURI()` `encodeURIComponent()` [here](http://stackoverflow.com/a/3608791/1748884).\n\nIt's worth mentioning that using `encodeURI()` and `encodeURIComponent()` has exactly 11 characters different.\nThese characters are: # $ \u0026 + , / : ; = ? @ [more discussion](http://stackoverflow.com/a/23842171/1748884).\n\n\u003ch2 align=\"center\"\u003e\n \u003cimg src=\"http://i.imgur.com/rHWC1r1.png\" alt=\"encodeuri or encodeuricomponent\"/\u003e\n\u003c/h2\u003e\n\n### YOU MIGHT NOT NEED JQUERY\n\nAs the title said, [you might not need jquery](http://youmightnotneedjquery.com/). It's really useful if you are looking for some utilities code - [AJAX](http://youmightnotneedjquery.com/#AJAX) [EFFECTS](http://youmightnotneedjquery.com/#effects), [ELEMENTS](http://youmightnotneedjquery.com/#elements), [EVENTS](http://youmightnotneedjquery.com/#events), [UTILS](http://youmightnotneedjquery.com/#utils)\n\n### You Don't Need jQuery\n\n\u003e Free yourself from the chains of jQuery by embracing and understanding the modern Web API and discovering various directed libraries to help you fill in the gaps.\n\n[http://blog.garstasio.com/you-dont-need-jquery/](http://blog.garstasio.com/you-dont-need-jquery/)\n\nUseful Tips\n\n1. [Selecting Elements](http://blog.garstasio.com/you-dont-need-jquery/selectors/)\n2. [DOM Manipulation](http://blog.garstasio.com/you-dont-need-jquery/dom-manipulation/)\n\n### Load Script with Callback\n\nIt's similar to [asynchronous script loading](#asynchronous-syntax) with additional callback event\n\n```js\nfunction loadScript(url, callback) {\n  var script = document.createElement('script');\n  script.async = true;\n  script.src = url;\n\n  var entry = document.getElementsByTagName('script')[0];\n  entry.parentNode.insertBefore(script, entry);\n\n  script.onload = script.onreadystatechange = function () {\n    var rdyState = script.readyState;\n\n    if (!rdyState || /complete|loaded/.test(script.readyState)) {\n      callback();\n\n      // detach the event handler to avoid memory leaks in IE (http://mng.bz/W8fx)\n      script.onload = null;\n      script.onreadystatechange = null;\n    }\n  };\n}\n```\n\n### Once Function\n\nImplementation of the function `once`\n\n\u003e Quite often, there are functions that are needed only to run once.  Oftentimes these functions are in the form of event listeners which may be difficult to manage.  Of course if they were easy to manage, it is advised to just remove the listeners. The following is the JavaScript function to make that possible!\n\n```js\n// Copy from DWB\n// http://davidwalsh.name/javascript-once\nfunction once(fn, context) {\n\tvar result;\n\n\treturn function() {\n\t\tif(fn) {\n\t\t\tresult = fn.apply(context || this, arguments);\n\t\t\tfn = null;\n\t\t}\n\n\t\treturn result;\n\t};\n}\n\n// Usage\nvar canOnlyFireOnce = once(function() {\n\tconsole.log('Fired!');\n});\n\ncanOnlyFireOnce(); // \"Fired!\"\ncanOnlyFireOnce(); // nada. nothing.\n```\n\n### Pixel Ratio Density\n\nTo better understand terms such as pixel, ratio, density, dimension are while developing mobile web -- the following links can provide more insights:\n\n- [Device pixel ratio - Mobile Web Development](https://www.youtube.com/watch?v=u0rfDeaxehc)\n- [Mobile device pixels - Mobile Web Development](https://www.youtube.com/watch?t=34\u0026v=UUF4jD-xoYc)\n\n### Get Style Value\n\n**Get inline-style value**\n\n```html\n\u003cspan id=\"black\" style=\"color: black\"\u003e This is black color span \u003c/span\u003e\n\u003cscript\u003e\n    document.getElementById('black').style.color; // =\u003e black\n\u003c/script\u003e\n```\n\n**Get Real style value**\n\n```html\n\u003cstyle\u003e\n#black {\n    color: red !important;\n}\n\u003c/style\u003e\n\n\u003cspan id=\"black\" style=\"color: black\"\u003e This is black color span \u003c/span\u003e\n\n\u003cscript\u003e\n    document.getElementById('black').style.color; // =\u003e black\n\n    // real\n    var black = document.getElementById('black');\n    window.getComputedStyle(black, null).getPropertyValue('color'); // =\u003e rgb(255, 0, 0)\n\u003c/script\u003e\n```\n\nref: [https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle)\n\n### Check if Element in Viewport\n\nThere is more [here](http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport/7557433#7557433).\n\n```js\nfunction isElementInViewport (el) {\n\n    //special bonus for those using jQuery\n    if (typeof jQuery === \"function\" \u0026\u0026 el instanceof jQuery) {\n        el = el[0];\n    }\n\n    var rect = el.getBoundingClientRect();\n\n    return (\n        rect.top \u003e= 0 \u0026\u0026\n        rect.left \u003e= 0 \u0026\u0026\n        rect.bottom \u003c= (window.innerHeight || document.documentElement.clientHeight) \u0026\u0026 /*or $(window).height() */\n        rect.right \u003c= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */\n    );\n}\n```\n\n### Check if Element is Visible\n\n```js\nvar isVisible = function(b) {\n    var a = window.getComputedStyle(b);\n    return 0 === a.getPropertyValue(\"opacity\") || \"none\" === a.getPropertyValue(\"display\") || \"hidden\" === a.getPropertyValue(\"visibility\") || 0 === parseInt(b.style.opacity, 10) || \"none\" === b.style.display || \"hidden\" === b.style.visibility ? false : true;\n}\n\nvar element = document.getElementById('box');\nisVisible(element); // =\u003e false or true\n```\n\n### Get Viewport Size\n\n```js\nvar getViewportSize = function() {\n    try {\n        var doc = top.document.documentElement\n          , g = (e = top.document.body) \u0026\u0026 top.document.clientWidth \u0026\u0026 top.document.clientHeight;\n    } catch (e) {\n        var doc = document.documentElement\n          , g = (e = document.body) \u0026\u0026 document.clientWidth \u0026\u0026 document.clientHeight;\n    }\n    var vp = [];\n    doc \u0026\u0026 doc.clientWidth \u0026\u0026 doc.clientHeight \u0026\u0026 (\"CSS1Compat\" === document.compatMode || !g) ? vp = [doc.clientWidth, doc.clientHeight] : g \u0026\u0026 (vp = [doc.clientWidth, doc.clientHeight]);\n    return vp;\n}\n\n// return as array [viewport_width, viewport_height]\n```\n\n### User Tracking\n\nAssuming that an Evil Advertisement Company wants to track a user, Evil may well generate a personalized unique hash by using [fingerprinting](https://github.com/Valve/fingerprintjs2). However, Ethical Company uses cookies and offers [Opt-out](https://en.wikipedia.org/wiki/Opt-out) solution.\n\n### Opt Out\n\n[DIGITAL ADVERTISING ALLIANCE, POWERED BY YOURADCHOICES](http://optout.aboutads.info/#!/) provides a tool that helps anyone to opt-out from all the participating companies.\n\n## WTF\n\n### Misspelling Of Referrer\n\nFun fact about why the HTTP Request Header having the field name `referer` not `referrer`\n\n_According to the [Wikipedia](https://en.wikipedia.org/wiki/HTTP_referer#Etymology)_\n\n\u003e The `misspelling of referrer` originated in the original proposal by computer scientist `Phillip Hallam-Baker` to incorporate the field into the HTTP specification. The misspelling was set in stone by the time of its incorporation into the `Request for Comments` standards document `RFC 1945`; document co-author `Roy Fielding` has remarked that neither \"referrer\" nor the misspelling \"referer\" were recognized by the standard `Unix spell checker` of the period. \"Referer\" has since become a widely used spelling in the industry when discussing HTTP referrers; usage of the misspelling is not universal, though, as the correct spelling \"referrer\" is used in some web specifications such as the `Document Object Model`.\n\n\u003ch2 align=\"center\"\u003e\n    \u003cimg src=\"https://cloud.githubusercontent.com/assets/2560096/12190613/96a7d652-b605-11e5-8109-1c6fefa9dfc4.png\"/\u003e\n\u003c/h2\u003e\n\n### CSS Flexible Box Layout Module\n\nBe sure to double-check the flexbox functionality in a different browser, especially the partial support in IE10/11.\n\n![image](https://user-images.githubusercontent.com/2560096/97968315-c7528d80-1dbe-11eb-8331-9ab1207a00a8.png)\n\n## Template\n\nThis guide provides **templates** and **boilerplates** to building an SDK. \n  \n- [TEMPLATE.md](./Template/README.md)\n\n## Books/Nice to Reads\n\n1. [Third-Party JavaScript](http://thirdpartyjs.com)\n2. [JQuery Plugin](https://learn.jquery.com/plugins/)\n3. [LightningJS](https://github.com/olark/lightningjs)\n\n*(inspired by [http-api-design](https://github.com/interagent/http-api-design))*\n\n## Contributors ✨\n\nThanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore --\u003e\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://www.linkedin.com/in/hueitan\"\u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/2560096?v=4\" width=\"100px;\" alt=\"Huei Tan\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eHuei Tan\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/hueitan/javascript-sdk-design/commits?author=hueitan\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/murindwaz\"\u003e\u003cimg src=\"https://avatars1.githubusercontent.com/u/259806?v=4\" width=\"100px;\" alt=\"Pascal Maniraho\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003ePascal Maniraho\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/hueitan/javascript-sdk-design/commits?author=murindwaz\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/adamellsworth\"\u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/7034617?v=4\" width=\"100px;\" alt=\"Adam\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAdam\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#content-adamellsworth\" title=\"Content\"\u003e🖋\u003c/a\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\nThis project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhueitan%2Fjavascript-sdk-design","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhueitan%2Fjavascript-sdk-design","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhueitan%2Fjavascript-sdk-design/lists"}