{"componentChunkName":"component---src-templates-blog-list-template-js","path":"/engineering/49","result":{"data":{"allMarkdownRemark":{"edges":[{"node":{"excerpt":"An API is an acronym for Application Programming Interface. API's include various tools, protocols, and routines. API's are used as a way…","fields":{"slug":"/engineering/what-is-an-api/"},"html":"<p>An API is an acronym for Application Programming Interface. API's include various tools, protocols, and routines. API's are used as a way for applications to communicate with various systems.</p>\n<p>But what does this mean? Well let me explain what they are with some examples. I am going to be using various API's for these examples.</p>\n<p><strong>Let's Begin</strong></p>\n<p>Let's start by looking at a favorite website of mine called The Yoda Speak Generator found <a href=\"https://lingojam.com/EnglishtoYoda\">here</a>.</p>\n<p>This website allows users to enter text and get a return of that same text formatted the way Yoda might say it. This is done with an API.</p>\n<p>Yoda Speak: Fun stuff, api's are! Yes, hmmm.</p>\n<p>API’s contain what is called an endpoint to access this API. The endpoint provides the connection to communicate with the API and give it some text to generate into Yoda Speak. The API would then return the generated Yoda Speak to the location of the request.</p>\n<p>Another way to think of an API is to think of it like an egg carton. An egg carton holds the eggs, protects them from damage and allows someone who wants to make breakfast a way to open and close the carton to access the eggs inside. The eggs inside would be the data, and the hand reaching into the carton would be much like the communication using an endpoint from a server.</p>\n<p>Okay, Let's make breakfast.... Just Kidding!</p>\n<p>For those of you who are visual Let's look at some examples of the code. These snippets are in PHP because it is my favorite language. Below is a link to download a small zip file called apidemo.zip.</p>\n<p>Demo Link</p>\n<p>You can host this directory on your localhost or on a website if you choose.</p>\n<p>After you have extracted the zip and have a directory such as localhost/apidemo open a browser and enter <code>http://localhost/apidemo/api.php?request=example&#x26;name=yourname</code> where localhost is your domain.</p>\n<p>To enter this endpoint in an application that makes API calls try Postman. Here is a <a href=\"http://www.getpostman.com/\">link</a> for a chrome extension.</p>\n<p>Try using a GET and a POST method with parameters request=example for the example function in api.php and name=yourname to output a name</p>\n<p>You should now see the output \"Your name is yourname\" in your browser</p>\n<p>explore the files api.php, API.class.php and MyAPI.php to explore how this simple API is taking in the parameters and outputting a name</p>\n<p>Hopefully, I have explained API's so you have a basic understanding of what they are. There are many types of API's, one that you may see often is RESTful API's, these unlike this example must abide by constraints that have been defined by the REST architecture.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"June 23, 2015","updated_date":null,"description":null,"title":"What is an API","tags":["API","Postman"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/2d243d0a5adf35bcbc0248f9e4a5054b/630fb/whats-an-api-300x300.png","srcSet":"/static/2d243d0a5adf35bcbc0248f9e4a5054b/69585/whats-an-api-300x300.png 200w,\n/static/2d243d0a5adf35bcbc0248f9e4a5054b/630fb/whats-an-api-300x300.png 300w","sizes":"(max-width: 300px) 100vw, 300px"}}},"author":{"id":"Zoie Carnegie","github":null,"avatar":null}}}},{"node":{"excerpt":"Let's face it, at some point you look at a radio or a checkbox button and you're like... this looks like something that starts with an \"s…","fields":{"slug":"/engineering/styling-radio-and-check-buttons-with-css/"},"html":"<p>Let's face it, at some point you look at a radio or a checkbox button and you're like... this looks like something that starts with an \"s\" and ends with a \"hit\". I'm here to stop you from saying that word and go on with your life without worrying about those ugly things.</p>\n<p>We're just going to use code here. No images, just pure scalable user interface using code. Cool, eh? Let's get started.</p>\n<p>Let's create our code structure first.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!-- </span><span class=\"mtk12\">Radio</span><span class=\"mtk1\"> --&gt; </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">label</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">input</span><span class=\"mtk1\"> </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;radio&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">I&#39;m a radio button</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">label</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!-- Checkbox --&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">label</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">input</span><span class=\"mtk1\"> </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">I&#39;m a checkbox</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">label</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<p>If it looks ugly, don't be alarmed. That's normal for an untamed code from the wild. All you gotta do now is to tame it with our very best tool, CSS.</p>\n<p>First thing you have to do is to hide the element that generates the hideous button, which is... DUN DUN DUN... the input tag. Don't worry, we can still trigger it even though it's hidden. How? by nesting it inside the label tag.</p>\n<p>Now that the default toggles are gone, we need to create our fake —but amazing— toggles.</p>\n<p><strong>Radio Button</strong></p>\n<p>We can't really customize this toggle that much because it needs other toggles to work properly. Let's just prettify it a bit.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">label</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;radio&quot;</span><span class=\"mtk1\">] {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">none</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">label</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;radio&quot;</span><span class=\"mtk1\">] ~ </span><span class=\"mtk6\">span</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">position</span><span class=\"mtk1\">: </span><span class=\"mtk8\">relative</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">inline-block</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">padding</span><span class=\"mtk1\">: </span><span class=\"mtk7\">3px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">0</span><span class=\"mtk1\"> </span><span class=\"mtk7\">3px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">25px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">label</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;radio&quot;</span><span class=\"mtk1\">] ~ </span><span class=\"mtk6\">span:before</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">content</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">position</span><span class=\"mtk1\">: </span><span class=\"mtk8\">absolute</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">block</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">width</span><span class=\"mtk1\">: </span><span class=\"mtk7\">18px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">height</span><span class=\"mtk1\">: </span><span class=\"mtk7\">18px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">background</span><span class=\"mtk1\">: </span><span class=\"mtk8\">#fff</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">margin-right</span><span class=\"mtk1\">: </span><span class=\"mtk7\">5px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">border</span><span class=\"mtk1\">: </span><span class=\"mtk7\">1px</span><span class=\"mtk1\"> </span><span class=\"mtk8\">solid</span><span class=\"mtk1\"> </span><span class=\"mtk8\">#ccc</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">border-radius</span><span class=\"mtk1\">: </span><span class=\"mtk7\">50%</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">left</span><span class=\"mtk1\">: </span><span class=\"mtk7\">0</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">top</span><span class=\"mtk1\">: </span><span class=\"mtk7\">0</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">box-sizing</span><span class=\"mtk1\">: </span><span class=\"mtk8\">border-box</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">transition</span><span class=\"mtk1\">: </span><span class=\"mtk8\">all</span><span class=\"mtk1\"> </span><span class=\"mtk7\">300ms</span><span class=\"mtk1\"> </span><span class=\"mtk8\">ease-in-out</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">label</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;radio&quot;</span><span class=\"mtk1\">]</span><span class=\"mtk6\">:checked</span><span class=\"mtk1\"> ~ </span><span class=\"mtk6\">span:before</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">border</span><span class=\"mtk1\">: </span><span class=\"mtk7\">5px</span><span class=\"mtk1\"> </span><span class=\"mtk8\">solid</span><span class=\"mtk1\"> </span><span class=\"mtk8\">#29d</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 182px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 23.626373626373624%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAzklEQVQY05WQyw7BQBSG+5b2XsQjsOiuCxHRtDZFhLgkwkIi4hJF4hLBRDFuIQ06c2ZG3Srs/Jtzyfny/znS6EgPDhNCcPG3JF9hE2jamyXq9HtojuyTvd8dVqultbD6ZncwnmCMR4Pher0w2+YMWQjN+dtH8pe2we4ZW9N8PlfOZmrVRjZdrJQKckjW1Xg4ptVb7YiiJJO6pmpRLZEyDGDwgvGFXYF7sQGAUOpOhBJCAShljLmFEAKMUeJ8xb5j/E7yh55brxH85xufG1c3pK8UXOSsdQoAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"checked-radio\"\n        title=\"checked-radio\"\n        src=\"/static/dd7aede644fb32d40c0126a61fa8e2b3/a51ee/checked-radio.png\"\n        srcset=\"/static/dd7aede644fb32d40c0126a61fa8e2b3/a51ee/checked-radio.png 182w\"\n        sizes=\"(max-width: 182px) 100vw, 182px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 167px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 23.952095808383234%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAuUlEQVQY06WOzQqCQBCAffa6dEwvejEPhiFETxGU/ZAYpd3EINIt0kZ33XXVVnuD+g4DA/MNn8R72p+QKKWMsbIkweV8jaI3QJameYHjBD2TOAj8O3pB+gjDG+T50fMQQkkSY1z2MmM151mWrp2lrmmblbOw7d32MDGt0WCoyLJhz113r6q6YeiKPLZMYzqzvZPfyd/spmnquuYVF48wxlXFRRHkQAjBRKyVmADAKC2KQpSKu05u/+ADkdIVMshhEA4AAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"unchecked-radio\"\n        title=\"unchecked-radio\"\n        src=\"/static/370b28a6fd25d3bb185d471d75d8cca9/21521/unchecked-radio.png\"\n        srcset=\"/static/370b28a6fd25d3bb185d471d75d8cca9/21521/unchecked-radio.png 167w\"\n        sizes=\"(max-width: 167px) 100vw, 167px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>By now it should like this.  </p>\n<p>Cleaner toggles!</p>\n<p><strong>Checkbox</strong></p>\n<p>This one is fun to customize because it has an on and off feature or a switch. Let's start with a simple toggle. We're going to transform this hideous toggle (screenshot) to this beautiful creature (screenshot).</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">label.spin</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">] {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">none</span><span class=\"mtk1\">; </span><span class=\"mtk3\">/*hides ugly toggle*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">label.spin</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">] ~ </span><span class=\"mtk6\">span</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">position</span><span class=\"mtk1\">: </span><span class=\"mtk8\">relative</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">inline-block</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">padding</span><span class=\"mtk1\">: </span><span class=\"mtk7\">3px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">0</span><span class=\"mtk1\"> </span><span class=\"mtk7\">3px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">25px</span><span class=\"mtk1\">; </span><span class=\"mtk3\">/*adds spacing on the left*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">/*create our new toggle*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">label.spin</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">] ~ </span><span class=\"mtk6\">span:before</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">content</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;</span><span class=\"mtk6\">\\2713</span><span class=\"mtk8\">&quot;</span><span class=\"mtk1\">; </span><span class=\"mtk3\">/*add a new check mark*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">text-align</span><span class=\"mtk1\">: </span><span class=\"mtk8\">center</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">font-size</span><span class=\"mtk1\">: </span><span class=\"mtk7\">13px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">position</span><span class=\"mtk1\">: </span><span class=\"mtk8\">absolute</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">block</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">width</span><span class=\"mtk1\">: </span><span class=\"mtk7\">18px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">height</span><span class=\"mtk1\">: </span><span class=\"mtk7\">18px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">background</span><span class=\"mtk1\">: </span><span class=\"mtk8\">#fff</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">color</span><span class=\"mtk1\">: </span><span class=\"mtk8\">#fff</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">margin-right</span><span class=\"mtk1\">: </span><span class=\"mtk7\">5px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">border</span><span class=\"mtk1\">: </span><span class=\"mtk7\">1px</span><span class=\"mtk1\"> </span><span class=\"mtk8\">solid</span><span class=\"mtk1\"> </span><span class=\"mtk8\">#ccc</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">border-radius</span><span class=\"mtk1\">: </span><span class=\"mtk7\">50%</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">left</span><span class=\"mtk1\">: </span><span class=\"mtk7\">0</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">top</span><span class=\"mtk1\">: </span><span class=\"mtk7\">0</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">box-sizing</span><span class=\"mtk1\">: </span><span class=\"mtk8\">border-box</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">transition</span><span class=\"mtk1\">: </span><span class=\"mtk8\">all</span><span class=\"mtk1\"> </span><span class=\"mtk7\">500ms</span><span class=\"mtk1\"> </span><span class=\"mtk8\">ease-in-out</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">/*if checked do this*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">label.spin</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">]</span><span class=\"mtk6\">:checked</span><span class=\"mtk1\"> ~ </span><span class=\"mtk6\">span:before</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">transform</span><span class=\"mtk1\">: </span><span class=\"mtk11\">rotatez</span><span class=\"mtk1\">(</span><span class=\"mtk7\">360deg</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">background</span><span class=\"mtk1\">: </span><span class=\"mtk8\">#29d</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">border-color</span><span class=\"mtk1\">: </span><span class=\"mtk8\">#29d</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Oh yes! Beautiful toggle.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 157px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 25.477707006369428%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA2klEQVQY023Py2rCUBAGYB+k79KN7+XabV14j6bWlnqBvoGrrgoiDboSOedokhaMyeSIPdeJMZui+MEMzGLmZ0rZBSopT0Kitdk/zK5cjVhMpbwqM/L47EXA0Ro4RIztOOfGaCmltRj44ZFzrWQKyc8+AkikUtoYRMyXsTwlD92N+DtprTYr7+NtMhiMveX38GX0NV+8991Oq1GrN1ynW31qOm7vddh32h1limQQ+pMl622Q31ZCpDHEcQoQE7rdF8LfkBAS+j7bBZRSRknejb0k30LEm18xu+8MtHsRCtP66PcAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"checked-check\"\n        title=\"checked-check\"\n        src=\"/static/3e1e005085688e17655e8f0b5963e4a7/fdd16/checked-check.png\"\n        srcset=\"/static/3e1e005085688e17655e8f0b5963e4a7/fdd16/checked-check.png 157w\"\n        sizes=\"(max-width: 157px) 100vw, 157px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 159px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 24.528301886792455%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA4UlEQVQY02WPQWvCQBCFc9L/418sFLxbgo1GbAm24EFavHlVFL15ENpA080mwaQxRpfN7rqZdRUEq98wMLxhePMMpZQsS04plxLUNXCuy/wfOAuGPBy4UuT7a12r0Y9BSkjgY0qp1oUQukMcsKLgjOXbbZQkhOwZF9oPAAy9KKRkUcQqVfH4sHTdN6sz+BwtZuN+fzieTN/btmk+mc1n22rVG81Xp/vSsXpO7+SsP0iybL1asfkcSllQmqdZviPpX+zjMI7jTbbxA4y83ygMPYQRQp73gzGG0/EdcBv9LvGFIxuREBwjsGf8AAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"unchecked-checkbox\"\n        title=\"unchecked-checkbox\"\n        src=\"/static/0d23223ae9ca968f75a80edb9d1cbaa7/f69fa/unchecked-checkbox.png\"\n        srcset=\"/static/0d23223ae9ca968f75a80edb9d1cbaa7/f69fa/unchecked-checkbox.png 159w\"\n        sizes=\"(max-width: 159px) 100vw, 159px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p><strong>Bonus!</strong></p>\n<p>Have you ever seen those toggles where it slides to the left and right when you click it? Did you know you can do that too using CSS? Let's try it.</p>\n<p>First, we're going to design the default look of an unchecked checkbox. By now you know that we need to hide the default toggle.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">label</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">] { </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">none</span><span class=\"mtk1\">; }</span></span></code></pre>\n<p>And then add a space on the left of the span using padding. While you're there, add a position relative to because we need to contain the rest of the elements inside the span.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">label</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">] ~ </span><span class=\"mtk6\">span</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">position</span><span class=\"mtk1\">: </span><span class=\"mtk8\">relative</span><span class=\"mtk1\">; </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">inline-block</span><span class=\"mtk1\">; </span><span class=\"mtk12\">padding</span><span class=\"mtk1\">: </span><span class=\"mtk7\">3px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">0</span><span class=\"mtk1\"> </span><span class=\"mtk7\">3px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">35px</span><span class=\"mtk1\">; }</span></span></code></pre>\n<p>Now, let's create our toggles using CSS pseudo element :before and :after. Why? Because generated CSS is easier to handle.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">label</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">] ~ </span><span class=\"mtk6\">span:before</span><span class=\"mtk1\">, </span><span class=\"mtk6\">label.slide</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">] ~ </span><span class=\"mtk6\">span:after</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">content</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">position</span><span class=\"mtk1\">: </span><span class=\"mtk8\">absolute</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">block</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">width</span><span class=\"mtk1\">: </span><span class=\"mtk7\">18px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">height</span><span class=\"mtk1\">: </span><span class=\"mtk7\">18px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">background</span><span class=\"mtk1\">: </span><span class=\"mtk8\">#fff</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">margin-right</span><span class=\"mtk1\">: </span><span class=\"mtk7\">5px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">border</span><span class=\"mtk1\">: </span><span class=\"mtk7\">1px</span><span class=\"mtk1\"> </span><span class=\"mtk8\">solid</span><span class=\"mtk1\"> </span><span class=\"mtk8\">#ccc</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">left</span><span class=\"mtk1\">: </span><span class=\"mtk7\">0</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">top</span><span class=\"mtk1\">: </span><span class=\"mtk7\">0</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">box-sizing</span><span class=\"mtk1\">: </span><span class=\"mtk8\">border-box</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">transition</span><span class=\"mtk1\">: </span><span class=\"mtk8\">all</span><span class=\"mtk1\"> </span><span class=\"mtk7\">300ms</span><span class=\"mtk1\"> </span><span class=\"mtk8\">ease-in-out</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>This will generate a box looking element. Since it's targeting both pseudo elements, they will look identical and on top of each other.</p>\n<p>It's time to start prettifying those pseudo elements.</p>\n<p>For :after, since this is the background where the :before toggle slides through. We need to modify the width to look bigger. Add an inset shadow to make it look like it's pushed through and a red background for an \"off\" effect.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">label</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">] ~ </span><span class=\"mtk6\">span:before</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">width</span><span class=\"mtk1\">: </span><span class=\"mtk7\">30px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">border-radius</span><span class=\"mtk1\">: </span><span class=\"mtk7\">20px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">box-shadow</span><span class=\"mtk1\">: </span><span class=\"mtk8\">inset</span><span class=\"mtk1\"> </span><span class=\"mtk7\">0</span><span class=\"mtk1\"> </span><span class=\"mtk7\">2px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">5px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">-1px</span><span class=\"mtk1\"> </span><span class=\"mtk11\">rgba</span><span class=\"mtk1\">(</span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0.4</span><span class=\"mtk1\">), </span><span class=\"mtk8\">inset</span><span class=\"mtk1\"> </span><span class=\"mtk7\">0</span><span class=\"mtk1\"> </span><span class=\"mtk7\">-2px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">0</span><span class=\"mtk1\"> </span><span class=\"mtk7\">-1px</span><span class=\"mtk1\"> </span><span class=\"mtk11\">rgba</span><span class=\"mtk1\">(</span><span class=\"mtk7\">255</span><span class=\"mtk1\">, </span><span class=\"mtk7\">255</span><span class=\"mtk1\">, </span><span class=\"mtk7\">255</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0.2</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">background</span><span class=\"mtk1\">: </span><span class=\"mtk8\">#F22613</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>For :before, we just need to make it look like a circle and lift it off a bit using box-shadow.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">label.slide</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">] ~ </span><span class=\"mtk6\">span:after</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">box-shadow</span><span class=\"mtk1\">: </span><span class=\"mtk7\">0</span><span class=\"mtk1\"> </span><span class=\"mtk7\">3px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">4px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">-2px</span><span class=\"mtk1\"> </span><span class=\"mtk11\">rgba</span><span class=\"mtk1\">(</span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0.5</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">border-radius</span><span class=\"mtk1\">: </span><span class=\"mtk7\">50%</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The \"on\" part just needs a little bit of pushing to the side and changing the background to blue or green.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">label.slide</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">]</span><span class=\"mtk6\">:checked</span><span class=\"mtk1\"> ~ </span><span class=\"mtk6\">span:before</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">background</span><span class=\"mtk1\">: </span><span class=\"mtk8\">#29d</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">label.slide</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">]</span><span class=\"mtk6\">:checked</span><span class=\"mtk1\"> ~ </span><span class=\"mtk6\">span:after</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">left</span><span class=\"mtk1\">: </span><span class=\"mtk7\">13px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The CSS is a bit longer here because there's a lot of elements that need to change, but take a chill pill because CSS won't slow your page down.</p>\n<p>And that's it. Your pretty checkbox or radio button toggles.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk17 { color: #808080; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk6 { color: #D7BA7D; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n</style>","frontmatter":{"date":"June 16, 2015","updated_date":null,"description":null,"title":"Styling Radio and Check buttons with CSS","tags":["CSS"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/56b8ac1b7f3b7dfdc03ce43aa1e62eaa/7d145/radio-check-buttons-css-1.png","srcSet":"/static/56b8ac1b7f3b7dfdc03ce43aa1e62eaa/69585/radio-check-buttons-css-1.png 200w,\n/static/56b8ac1b7f3b7dfdc03ce43aa1e62eaa/497c6/radio-check-buttons-css-1.png 400w,\n/static/56b8ac1b7f3b7dfdc03ce43aa1e62eaa/7d145/radio-check-buttons-css-1.png 610w","sizes":"(max-width: 610px) 100vw, 610px"}}},"author":{"id":"Team LoginRadius","github":"LoginRadius","avatar":null}}}},{"node":{"excerpt":"Social sharing button offers an easy way to distribute your content to a wider audience. The major social providers allow options to…","fields":{"slug":"/engineering/configuring-social-sharing-buttons/"},"html":"<p>Social sharing button offers an easy way to distribute your content to a wider audience. The major social providers allow options to configure the content that will be shared programmatically. In this guide we explore the options that you can use in order to configure the shared content of your social shares including: Message, URL, Image, and Image Caption/Description.</p>\n<p><strong>Facebook</strong></p>\n<p>Facebook utilizes Open Graph Tags which are meta tags that can be included on your page and are scrapped by Facebook when determining the content that should be shared with a specific button. These tags can be included in the head section of your page. All meta tags should be formatted with a property value of \"og:<tag-name>\", some useful tag names are:</p>\n<ul>\n<li>title- The title of your article.</li>\n<li>type- The media content that is included in the shared article. This is defaulted to \"website\".</li>\n<li>image- The image that will be included in the share.</li>\n<li>url- The canonical URL that will be used to identify the share and aggregate the community shares/likes.</li>\n<li>description- A  brief description that is displayed below the image in the share.</li>\n</ul>\n<p>Example of og meta tags that can be included in your html head tag:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>If you are modifying these tags it can take some time for the changes to translate over to Facebook. You can refer to <a href=\"/social-provider-social-sharing-troubleshooting-resources/\">this blog</a> on troubleshooting, testing, and force updating your configured sharing systems.</p>\n<p><strong>Google</strong></p>\n<p>Google offers multiple ways that you can set the shared content which it intelligently determines the most relevant details to be displayed in the share. This works to varying degrees with the following options available and taking precedence respectively:</p>\n<ul>\n<li>Structured Data Markup- HTML markup detailed on <a href=\"http://schema.org/\">Schema</a>.</li>\n<li>Open Graph Tags- Turn your page into a rich data object, commonly used to customize Facebook sharing details. Information on the markup is available on <a href=\"http://ogp.me/\">OGP</a></li>\n<li>Title or Meta Description- HTML attributes that provide details on the site.</li>\n<li>Google’s best guess- If none of the above are included, Google will crawl your page and try to interpret the most suitable details to include in the share.</li>\n</ul>\n<p>Below is an example of basic structured data markup:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk12\">Your</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Site</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Title</span><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">A</span><span class=\"mtk1\"> </span><span class=\"mtk12\">description</span><span class=\"mtk1\"> </span><span class=\"mtk4\">of</span><span class=\"mtk1\"> </span><span class=\"mtk12\">your</span><span class=\"mtk1\"> </span><span class=\"mtk12\">site</span><span class=\"mtk1\">.</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>Below is an example of using basic meta tags to define the shared content:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p><strong>Twitter</strong></p>\n<p>The best way to customize your Twitter shares is to modify the URL query string parameters that gets triggered when the share icon is clicked. Another way is to customize the <code>&#x3C;a></code> tag by including data-attribute tags as detailed on Twitters <a href=\"https://developer.twitter.com/en/docs/twitter-for-websites/tweet-button/overview\">Tweet button creation instructions</a> . If you do not have control over the links or triggers that are being used to activate the Tweet popup you can also set Twitter Card meta tags which handle the Twitter customizations.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>Various providers will utilize some of the above methods with open graph tags being one of the most common methods for controlling the shared content. Other systems will customize this content based off of parameters that are passed into the script or URL that is used to trigger the share interface. Getting these to be correctly configured can be a bit of a trial and error process, you can use the resources detailed in <a href=\"/social-provider-social-sharing-troubleshooting-resources/\">this blog post</a> to help test and verify that you have correctly configured your social sharing content.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n</style>","frontmatter":{"date":"June 09, 2015","updated_date":null,"description":null,"title":"Configuring Your Social Sharing Buttons","tags":["SocialSharing"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/238b1852ad4d0bf59dc00d0079239993/630fb/configuring-social-share-buttons-300x300.png","srcSet":"/static/238b1852ad4d0bf59dc00d0079239993/69585/configuring-social-share-buttons-300x300.png 200w,\n/static/238b1852ad4d0bf59dc00d0079239993/630fb/configuring-social-share-buttons-300x300.png 300w","sizes":"(max-width: 300px) 100vw, 300px"}}},"author":{"id":"Karl Wittig","github":null,"avatar":null}}}},{"node":{"excerpt":"Recently, I was working on an implementation to build an embedded app on Shopify with PHP. I realized that the 3rd party PHP SDK recommended…","fields":{"slug":"/engineering/shopify-embedded-app/"},"html":"<p>Recently, I was working on an implementation to build an embedded app on Shopify with PHP. I realized that the 3rd party PHP SDK recommended by Shopify called \"phpish\" does not support the feature to \"PUT\" assets into your shopify shop's theme. The link to \"phpish\" git repository can be found  <a href=\"https://github.com/phpish/shopify\">here</a>, I'd like to thank these guys for their great work, it saved me lots of time to get the implementation on the right track.</p>\n<p>So if you want to do a PUT API call to Shopify web service, you can do it in raw PHP by customizing a CURL request, this is not very hard. But prior to make the Asset API call, first you need to retrieve the currently activated theme ID by calling the Shopify Theme API call, this part can be done easily with the help of phpish.</p>\n<p>Then it is the time to customize your CURL request to do the PUT API call, remember phpish stores our information such as Oauth Token and Shop into the $_SESSION, we can leverage on that or manually fill in the correct information</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"php\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!-- </span><span class=\"mtk11\">array</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;key&quot;</span><span class=\"mtk1\"> =&gt; </span><span class=\"mtk8\">&quot;snippets/put-asset.liquid&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;value&quot;</span><span class=\"mtk1\"> =&gt; </span><span class=\"mtk8\">&quot;this is a test to put assets&quot;</span><span class=\"mtk1\">));</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">$ch</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">curl_init</span><span class=\"mtk1\">(</span><span class=\"mtk12\">$_SESSION</span><span class=\"mtk1\">[</span><span class=\"mtk8\">&#39;shop&#39;</span><span class=\"mtk1\">].</span><span class=\"mtk8\">&quot;/admin/themes/</span><span class=\"mtk12\">$theme_id</span><span class=\"mtk8\">/assets.json&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">curl_setopt</span><span class=\"mtk1\">(</span><span class=\"mtk12\">$ch</span><span class=\"mtk1\">, CURLOPT_RETURNTRANSFER, </span><span class=\"mtk4\">true</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">curl_setopt</span><span class=\"mtk1\">(</span><span class=\"mtk12\">$ch</span><span class=\"mtk1\">, CURLOPT_CUSTOMREQUEST, </span><span class=\"mtk8\">&quot;PUT&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">$headers</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">array</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">$headers</span><span class=\"mtk1\">[] = </span><span class=\"mtk8\">&quot;X-Shopify-Access-Token: &quot;</span><span class=\"mtk1\">.</span><span class=\"mtk11\">echo</span><span class=\"mtk1\"> </span><span class=\"mtk12\">$_SESSION</span><span class=\"mtk1\">[</span><span class=\"mtk8\">&#39;oauth_token&#39;</span><span class=\"mtk1\">];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">$headers</span><span class=\"mtk1\">[] = </span><span class=\"mtk8\">&quot;Content-Type: application/json&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">curl_setopt</span><span class=\"mtk1\">( </span><span class=\"mtk12\">$ch</span><span class=\"mtk1\">, CURLOPT_HTTPHEADER, </span><span class=\"mtk12\">$headers</span><span class=\"mtk1\"> );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">curl_setopt</span><span class=\"mtk1\">( </span><span class=\"mtk12\">$ch</span><span class=\"mtk1\">, CURLOPT_POSTFIELDS, </span><span class=\"mtk11\">json_encode</span><span class=\"mtk1\">(</span><span class=\"mtk12\">$data</span><span class=\"mtk1\">));</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">$response</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">curl_exec</span><span class=\"mtk1\">(</span><span class=\"mtk12\">$ch</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">echo</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">echo</span><span class=\"mtk1\"> </span><span class=\"mtk11\">curl_error</span><span class=\"mtk1\">(</span><span class=\"mtk12\">$ch</span><span class=\"mtk1\">).</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">var_dump</span><span class=\"mtk1\">(</span><span class=\"mtk12\">$response</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">curl_close</span><span class=\"mtk1\">(</span><span class=\"mtk12\">$ch</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">?&gt;--&gt;</span></span></code></pre>\n<p>Let me briefly explain this snippet, so first you define an array with key and value, key maps to the file name that you want to create, and value is the actual code or asset you want to pass in. Then you create a curl request with method \"PUT\" like all the other requests</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"php\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">$ch</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">curl_init</span><span class=\"mtk1\">(</span><span class=\"mtk12\">$_SESSION</span><span class=\"mtk1\">[</span><span class=\"mtk8\">&#39;shop&#39;</span><span class=\"mtk1\">].</span><span class=\"mtk8\">&quot;/admin/themes/</span><span class=\"mtk12\">$theme_id</span><span class=\"mtk8\">/assets.json&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">curl_setopt</span><span class=\"mtk1\">(</span><span class=\"mtk12\">$ch</span><span class=\"mtk1\">, CURLOPT_RETURNTRANSFER, </span><span class=\"mtk4\">true</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">curl_setopt</span><span class=\"mtk1\">(</span><span class=\"mtk12\">$ch</span><span class=\"mtk1\">, CURLOPT_CUSTOMREQUEST, </span><span class=\"mtk8\">&quot;PUT&quot;</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>Next is something special for Shopify, to make an API call to Shopify you have to specify Oauth_Token in your request to tell Shopify who you are, and so does Content-Type.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"php\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">$headers</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">array</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">$headers</span><span class=\"mtk1\">[] = </span><span class=\"mtk8\">&quot;X-Shopify-Access-Token: &quot;</span><span class=\"mtk1\">.</span><span class=\"mtk11\">echo</span><span class=\"mtk1\"> </span><span class=\"mtk12\">$_SESSION</span><span class=\"mtk1\">[</span><span class=\"mtk8\">&#39;oauth_token&#39;</span><span class=\"mtk1\">];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">$headers</span><span class=\"mtk1\">[] = </span><span class=\"mtk8\">&quot;Content-Type: application/json&quot;</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>Last but not least, json encode your data array into JSON format and send the request.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"php\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">curl_setopt</span><span class=\"mtk1\">( </span><span class=\"mtk12\">$ch</span><span class=\"mtk1\">, CURLOPT_POSTFIELDS, </span><span class=\"mtk11\">json_encode</span><span class=\"mtk1\">(</span><span class=\"mtk12\">$data</span><span class=\"mtk1\">));</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">$response</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">curl_exec</span><span class=\"mtk1\">(</span><span class=\"mtk12\">$ch</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>The last part is just to catch the returned response or show the error message from your CURL request if something is going wrong.</p>\n<p>Hope this can help someone, happy coding.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n</style>","frontmatter":{"date":"June 02, 2015","updated_date":null,"description":null,"title":"Shopify Embedded App","tags":["Shopify","PHP"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.8867924528301887,"src":"/static/4872b27152104126f3a84ce3bb3dc334/2b011/shopify.png","srcSet":"/static/4872b27152104126f3a84ce3bb3dc334/69585/shopify.png 200w,\n/static/4872b27152104126f3a84ce3bb3dc334/2b011/shopify.png 308w","sizes":"(max-width: 308px) 100vw, 308px"}}},"author":{"id":"Lucius Yu","github":null,"avatar":null}}}},{"node":{"excerpt":"Are you having trouble with accessing API endpoint?   Unsure why your API is not returning data? Most modern browsers have tools or plugins…","fields":{"slug":"/engineering/api-debugging-tools/"},"html":"<p><strong>Are you having trouble with accessing API endpoint?</strong>   <strong>Unsure why your API is not returning data?</strong> Most modern browsers have tools or plugins that allows you to quickly and easily test your API calls and see the sample returned data. In this post we go through some tools available for common browsers and web tools that will cut down the total troubleshooting time.</p>\n<h2 id=\"google-chrome\" style=\"position:relative;\"><a href=\"#google-chrome\" aria-label=\"google chrome permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Google Chrome</h2>\n<p>Chrome offers a wide variety of apps that are quick and easy to install through the <a href=\"https://chrome.google.com/webstore/\">Chrome app webstore</a>. <a href=\"http://www.getpostman.com/\">Postman</a> is one of those app and it offers a very robust REST API testing solution. It allows you to quickly create and format a wide range of API calls, and keeps a record of previously accessed APIs for easy reference and reuse. Postman have an easy to understand interface that allows you to quickly reformat the included parameters, headers, and form data. Returned data can be viewed in multiple different formats depending on your preferences.</p>\n<p>Another added benefit of Postman is its built-in support for common authentication procedures like: Basic Auth, Digest Auth, and OAuth 1.0/2.0. These \"helpers\" allow you to bypass some of the common tasks that can be troublesome in the mentioned protocols such as signing your request(OAuth 1.0) or requesting an Access token(OAuth 2.0).</p>\n<h2 id=\"mozilla-firefox\" style=\"position:relative;\"><a href=\"#mozilla-firefox\" aria-label=\"mozilla firefox permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Mozilla Firefox</h2>\n<p>Poster or RestClient are both useful tools that allow you to test out your API calls within Mozilla Firefox. They offer many similar systems as Postman, allowing you to set various parts of your API quickly and easily. With built in features to set such as Base URL, Auth method, Timeout, Action, Content, headers, and query parameters; It returns a complete response object allowing you to troubleshoot APIs before integrating them into your systems. Both RestClient and Poster allow you to save your requests for future use.</p>\n<h2 id=\"other-systems\" style=\"position:relative;\"><a href=\"#other-systems\" aria-label=\"other systems permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Other Systems</h2>\n<p><strong>Runscope:</strong> This is a powerful tool that allows you to set up test cases for your APIs. Which makes it easy for you to not only handle many of the features as described in the above two systems, but to also schedule these requests to perform periodically. This allows you to monitor your APIs and have email notifications sent out when specific conditions are met. You can also mask the API requests to run them from different locations worldwide allowing you to test user cases from a global audience.</p>\n<p><strong>SoapUI:</strong> This is an extremely robust solution that can handle your entire testing environment. It also have built in features to test out RESTful API calls, as well as SOAP calls. This solution is very extensive and has many options that cover the full suite of features detailed in the above technologies. On top of that, they have a well formatted instructions available on their site, detailing how to setup and configure the program.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"May 26, 2015","updated_date":null,"description":null,"title":"API Debugging Tools","tags":["Engineering","GoogleChorme","MozilaFirefox","SoupUI","RunScope"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/949b6e4da71216d7a55b82e01a8bcaa1/630fb/api_debugging-tools-300x300.png","srcSet":"/static/949b6e4da71216d7a55b82e01a8bcaa1/69585/api_debugging-tools-300x300.png 200w,\n/static/949b6e4da71216d7a55b82e01a8bcaa1/630fb/api_debugging-tools-300x300.png 300w","sizes":"(max-width: 300px) 100vw, 300px"}}},"author":{"id":"Karl Wittig","github":null,"avatar":null}}}},{"node":{"excerpt":"Overview Filter Portfolio can be very useful for websites, especially when there is a lot of images you want to show to users. It is always…","fields":{"slug":"/engineering/use-php-to-generate-filter-portfolio/"},"html":"<p><strong>Overview</strong></p>\n<p>Filter Portfolio can be very useful for websites, especially when there is a lot of images you want to show to users. It is always nice to keep it into different categories and allow your user to play with them.</p>\n<p>But adding a tag and a div on hundreds of images is definitely not fun. Our goal today is to use PHP to generate the Filter Portfolio instead of manually adding them one by one.</p>\n<p>The logic is like this, first we have a folder to contain all the portfolio images. It could be like this:</p>\n<p>\"assets->img->logos->businesses\"</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 670px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 58.00000000000001%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAABVUlEQVQoz8WRz04CMRDG9+V9AA++hheNBwXUSDSCEdEAahRkYbfl32a72+522g5jV4zRxAPx4nea9ptf5ps20HKKTlmHWnFTLpxD0AJKbi0YA1pF1siN62BVuWUKKkaEoiiCbHGx5CERlaItlk+4JqeHfFQzxhBBwuoi5d6F/CYOO4iEMEzYtS4KAAj4y+H1aZOslfPGbNK3jlze7TT2UmGJbOto57bd9LCcn7Qu6xbJqd6oV5vFmXUmYOF9FDEAK1bDcPwqFZDL2GSQy5II2fhuGkYeTvhjFA6zvECT8ukgz1U1WYp5JhLEtYVcF6lzzrci4qbw2hQOCcBY6+P4lNb3a62D1G+VvFbBVleLuOupD2RNn/oqvqu6rOD++W7v4dgfps/7Z7WDsoTKXP/K/FAFs7cWY7FPVYgXHo00GNpOFezfXEn18TEkc7nZaluY/qp/hd8Bhl60n/dN47sAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"folder-structure\"\n        title=\"folder-structure\"\n        src=\"/static/d4a3eedb9dab04f462db04bf921452f6/d67fd/folder-structure.png\"\n        srcset=\"/static/d4a3eedb9dab04f462db04bf921452f6/a6d36/folder-structure.png 650w,\n/static/d4a3eedb9dab04f462db04bf921452f6/d67fd/folder-structure.png 670w\"\n        sizes=\"(max-width: 670px) 100vw, 670px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>And in the \"businesses\" folder, we have some sub-folders to put all the images in different categories, like this:  </p>\n<p>Each sub-folder contains different images in that category, and our goal is to use those sub-folders name as the filters, and the images under each category will be added automatically. Let's do it.</p>\n<ul>\n<li>First we need to implement a filter portfolio.</li>\n</ul>\n<p>I know people hate this, but we are going to use a little pre-built javascript file called MixitUp, I promise it is a very easy but powerful tool to use, see a <a href=\"http://www.jqueryrain.com/?URGti1_4\">demo here</a>.</p>\n<p>There is already very comprehensive tutorial on how to install that plugin  in their <a href=\"https://github.com/patrickkunka/mixitup\">github</a> repository, you can follow either of these.</p>\n<ol>\n<li><strong>Download the javascript file from github</strong></li>\n</ol>\n<p>Click this link <a href=\"https://github.com/patrickkunka/mixitup/tree/v3/src\">git -> src</a> to open the repository for the javascript file, download and save it in your asset folder.</p>\n<ol>\n<li><strong>Import js and css</strong></li>\n</ol>\n<p>You can do this right before the closing body tag. You probably have Jquery installed already, but just in case you don't.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>It is recommended to link your Mixitup function while your document is ready, so add this after the importing lines.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">$</span><span class=\"mtk1\">(</span><span class=\"mtk12\">document</span><span class=\"mtk1\">).</span><span class=\"mtk11\">ready</span><span class=\"mtk1\">(</span><span class=\"mtk4\">function</span><span class=\"mtk1\">(){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">jQuery</span><span class=\"mtk1\">(</span><span class=\"mtk4\">function</span><span class=\"mtk1\">(){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">$</span><span class=\"mtk1\">(</span><span class=\"mtk4\">function</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk11\">$</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;#Container&#39;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">mixItUp</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<ol>\n<li><strong>Add the code</strong></li>\n</ol>\n<p>Here is where the fun begins! I am not going to do any stylings in this tutorial, since you can always customize it yourself. Okay, first of first, add a div as a container of your filter portfolio section, so:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!----&gt;</span></span></code></pre>\n<p>Next, we need to add those clickable filter buttons to the div we just created. We can add them programmatically, but to be honest, it is not that bad to do it manually.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!-- </span><span class=\"mtk12\">All</span><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk12\">Eateries</span><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk12\">Cafes</span><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk12\">Bars</span><span class=\"mtk1\">, </span><span class=\"mtk12\">Clubs</span><span class=\"mtk1\"> & </span><span class=\"mtk12\">Lounges</span><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk12\">Lifestyle</span><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk12\">Health</span><span class=\"mtk1\"> & </span><span class=\"mtk12\">Fitness</span><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk12\">Fashion</span><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk12\">Beauty</span><span class=\"mtk1\"> & </span><span class=\"mtk12\">Spas</span><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk12\">Entertainment</span><span class=\"mtk1\"> --&gt;</span></span></code></pre>\n<p>Please note, for these <code>&#x3C;a></code> tags, you need to follow the patterns of MixitUp. Basically in class attribute you need to specify \"filter\" for it, and in data-filter, you need to tell which category it is. Next we are going to write some PHP code, to iterate through the destination folder, and process the files within it.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"php\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">valid</span><span class=\"mtk1\">()) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (!</span><span class=\"mtk12\">$it</span><span class=\"mtk1\">-&gt;</span><span class=\"mtk11\">isDot</span><span class=\"mtk1\">()) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">$subject</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">$it</span><span class=\"mtk1\">-&gt;</span><span class=\"mtk11\">getSubPathName</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk3\">// Mac OS automatically creates .DS_store file to store metadata</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk3\">// The following regex is used to ignore those files</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">$pattern</span><span class=\"mtk1\"> = </span><span class=\"mtk5\">&#39;/</span><span class=\"mtk6\">\\\\.</span><span class=\"mtk5\">DS/&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">preg_match</span><span class=\"mtk1\">( </span><span class=\"mtk12\">$pattern</span><span class=\"mtk1\">, </span><span class=\"mtk12\">$subject</span><span class=\"mtk1\">, </span><span class=\"mtk12\">$match</span><span class=\"mtk1\"> );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\">( !</span><span class=\"mtk12\">$match</span><span class=\"mtk1\"> ) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk12\">$file_path_name</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">str_replace</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;</span><span class=\"mtk6\">\\\\</span><span class=\"mtk8\">&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;/&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">$subject</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">?&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    &lt;div </span><span class=\"mtk4\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;mix getSubPath(); ?&gt; col-md-3 &quot;</span><span class=\"mtk1\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        &lt;img src=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\"> alt=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk4\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;business-logo-img&quot;</span><span class=\"mtk1\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">next</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">?&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>The code is pretty straightforward, just want to label out a couple of things.</p>\n<p>First, we specified which folders we are working with and then we used a built-in recursive iterators to cycle through the folder.</p>\n<p>For each item we found in every sub-folder, $it->getSubPath will return the sub-folder name and $it->getSubPathName will return the name of the file. Create a div for each image, and play with those returned parameters to fit them into the pattern of MixitUp.</p>\n<p>The $it->isDot() function and regular expressions are used to filter out some system hidden files such as \".DS_Store\" and others, since we do not want to them to be shown as images.</p>\n<p>Easy, right? If you like this post, click share and help people who's having this kind of issue.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk5 { color: #D16969; }\n  .dark-default-dark .mtk6 { color: #D7BA7D; }\n</style>","frontmatter":{"date":"May 19, 2015","updated_date":null,"description":null,"title":"Use PHP to generate filter portfolio","tags":["PHP"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/1ea6f04417f886989e6dc30837c305f5/7d145/php-filter-portfolio.png","srcSet":"/static/1ea6f04417f886989e6dc30837c305f5/69585/php-filter-portfolio.png 200w,\n/static/1ea6f04417f886989e6dc30837c305f5/497c6/php-filter-portfolio.png 400w,\n/static/1ea6f04417f886989e6dc30837c305f5/7d145/php-filter-portfolio.png 610w","sizes":"(max-width: 610px) 100vw, 610px"}}},"author":{"id":"Lucius Yu","github":null,"avatar":null}}}}]},"markdownRemark":{"excerpt":"Google has prepared a roadmap to restrict third-party cookies in Chrome. Since 04 January 2024, Chrome has rolled out third-party cookie…","fields":{"slug":"/engineering/identity-impact-of-google-chrome-thirdparty-cookie-restrictions/"},"html":"<p>Google has prepared a roadmap to restrict third-party cookies in Chrome. Since 04 January 2024, Chrome has rolled out third-party cookie restrictions for 1% of stable clients and 20% of Canary, Dev, and Beta clients.</p>\n<p><strong>What does it mean for user authentication?</strong></p>\n<p>On one hand, Google believes third-party cookies are widely used for cross-site tracking, greatly affecting user privacy. Hence, Google wants to phase out (or restrict) supporting third-party cookies in Chrome by early Q2 2025 (subject to regulatory processes).</p>\n<p>On the other hand, Google introduced Privacy Sandbox to support the use cases (other than cross-site tracking and advertising) previously implemented using third-party cookies.</p>\n<p>In this article, we’ll discuss:</p>\n<ul>\n<li>How is user authentication (identity) affected?</li>\n<li>What is Google offering as part of Privacy Sandbox to support various identity use cases when third-party cookies are phased out?</li>\n</ul>\n<h2 id=\"how-is-user-authentication-affected\" style=\"position:relative;\"><a href=\"#how-is-user-authentication-affected\" aria-label=\"how is user authentication affected permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How is User Authentication Affected?</h2>\n<p>Third-party cookie restrictions affect user authentication in three ways, as follows.</p>\n<h3 id=\"external-identity-providers\" style=\"position:relative;\"><a href=\"#external-identity-providers\" aria-label=\"external identity providers permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>External Identity Providers</h3>\n<p>If your website or app uses an external Identity Provider (IdP) — like LoginRadius, the IdP sets a third-party cookie when the user authenticates on your app.</p>\n<h3 id=\"web-sso\" style=\"position:relative;\"><a href=\"#web-sso\" aria-label=\"web sso permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Web SSO</h3>\n<p>If you have multiple apps across domains within your organization and authentication is handled using an IdP (internal or external) with web SSO, you already use third-party cookies to facilitate seamless access for each user using a single set of credentials.</p>\n<p>If you have implemented web SSO with one primary domain and multiple sub-domains of the primary domain, third-party cookie restrictions may not apply. For now, Google doesn’t consider the cookies set by sub-domains as third-party cookies, although this stance may change in the future.</p>\n<p>For example, you have apps at <code>example.com</code>, <code>travel.example.com</code>, <code>stay.example.com</code>, and web SSO is handled by <code>auth.example.com</code>. In this case, third-party cookie restrictions don’t apply.</p>\n<h3 id=\"federated-sso\" style=\"position:relative;\"><a href=\"#federated-sso\" aria-label=\"federated sso permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Federated SSO</h3>\n<p>Federated SSO is similar to, albeit different from, web SSO. It can handle multiple IdPs and applications—aka., Service Providers (SPs)—spanning multiple organizations. It can also implement authentication scenarios that are usually implemented through web SSO.</p>\n<p>Usually, authentication is handled on a separate pop-up or page when the user wants to authenticate rather than on the application or website a user visits. </p>\n<p>For example, you already use federated SSO if you facilitate authentication for a set of apps through multiple social identity providers as well as traditional usernames and passwords.</p>\n<blockquote>\n<p><strong>Note</strong>: It is also possible to store tokens locally, not within cookies. In this case, third-party cookie restrictions won’t affect token-based authentication. However, the restrictions still affect authentication where tokens are stored within third-party cookies (a common and secure method).</p>\n</blockquote>\n<h2 id=\"chromes-alternatives-for-third-party-cookies\" style=\"position:relative;\"><a href=\"#chromes-alternatives-for-third-party-cookies\" aria-label=\"chromes alternatives for third party cookies permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Chrome’s Alternatives for Third-Party Cookies</h2>\n<p>Google has been developing alternative features and capabilities for Chrome to replace third-party cookies as part of its Privacy Sandbox for Web initiative.</p>\n<p>Specific to authentication, Google recommends the following:</p>\n<ol>\n<li>Cookies Having Independent Partitioned State (CHIPS)</li>\n<li>Storage Access API</li>\n<li>Related Website Sets</li>\n<li>Federated Credential Management (FedCM) API</li>\n</ol>\n<h3 id=\"cookies-having-independent-partitioned-state-chips\" style=\"position:relative;\"><a href=\"#cookies-having-independent-partitioned-state-chips\" aria-label=\"cookies having independent partitioned state chips permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Cookies Having Independent Partitioned State (CHIPS)</h3>\n<p><a href=\"https://developers.google.com/privacy-sandbox/3pcd/chips\">CHIPS</a> are a restricted way of setting third-party cookies on a top-level site without making them accessible on other top-level sites. Thus, they limit cross-site tracking and enable specific cross-site functionalities, such as maps, chat, and payment embeds.</p>\n<p>For example, a user visits <code>a.com</code> with a map embed from <code>map-example.com</code>, which can set a partitioned cookie that is only accessible on a.com. </p>\n<p>If the user visits <code>b.com</code> with a map embed from <code>map-example.com</code>, it cannot access the partitioned cookie set on <code>a.com</code>. It has to create a separate partitioned cookie specific to <code>b.com</code>, thus blocking cross-site tracking yet allowing limited cross-site functionality.</p>\n<p>You should specifically opt for partitioned cookies (CHIPS), which are set with partitioned and secure cookie attributes.</p>\n<p>If you’re using an external identity provider for your application, CHIPS is a good option to supplant third-party cookie restrictions. </p>\n<p>However, CHIPS may not be ideal if you have a web SSO or federated SSO implementation. It creates separate partitioned cookies for each application with a separate domain, which can increase complexity and create compatibility issues.</p>\n<h3 id=\"storage-access-api\" style=\"position:relative;\"><a href=\"#storage-access-api\" aria-label=\"storage access api permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Storage Access API</h3>\n<p>With <a href=\"https://developers.google.com/privacy-sandbox/3pcd/storage-access-api\">Storage Access API</a>, you can access the local storage in a third-party context through iframes, similar to when users visit it as a top-level site in a first-party context. That is, it gives access to unpartitioned cookies and storage.</p>\n<p>Storage Access API requires explicit user approval to grant access, similar to locations, camera, and microphone permissions. If the user denies access, unpartitioned cookies and storage won’t be accessible in a third-party context.</p>\n<p>It is most suitable when loading cross-site resources and interactions, such as:</p>\n<p>Verifying user sessions when allowing interactions on an embedded social post or providing personalization for an embedded video.\nEmbedded documents requiring user verification status to be accessible.</p>\n<p>As it requires explicit user approval, it is advisable to use Storage Access API when you can’t implement an identity use case with the other options.</p>\n<h3 id=\"related-website-sets\" style=\"position:relative;\"><a href=\"#related-website-sets\" aria-label=\"related website sets permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Related Website Sets</h3>\n<p>With <a href=\"https://developers.google.com/privacy-sandbox/3pcd/related-website-sets\">Related Website Sets</a>, you can declare a <code>primary</code> website and <code>associatedSites</code> for limited purposes to grant third-party cookie access and local storage for a limited number of sites.</p>\n<p>Chrome automatically recognizes related website sets declared, accepted, and maintained in this open-source GitHub repository: <a href=\"https://github.com/GoogleChrome/related-website-sets\">Related Website Sets</a></p>\n<p>It provides access through Storage Access API directly without prompting for user approval, but only after the user interacts with the relevant iframe.</p>\n<p>It is important to declare a limited number of domains in related website sets that are meaningful and used for specific purposes. Google may block or suspend any exploitative use of this feature.</p>\n<p>The top-level site can also request approval for specific cross-site resources and scripts to Storage Access API using <code>resuestStorageAccessFor()</code> API.</p>\n<p>If you’re using an external identity provider for your web application, you can declare the domain of the identity provider in the related set to ensure limited third-party cookies and storage access to the identity provider, thus ensuring seamless user authentication.</p>\n<p>Related Website Sets can also work to supplement third-party cookie restrictions in web SSO and federated SSO if the number of web applications (or domains) is limited.</p>\n<h3 id=\"federated-credential-management-fedcm-api\" style=\"position:relative;\"><a href=\"#federated-credential-management-fedcm-api\" aria-label=\"federated credential management fedcm api permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Federated Credential Management (FedCM) API</h3>\n<p>FedCM API enables federated SSO without third-party cookies.</p>\n<p>With FedCM API, a user follows these steps for authentication:</p>\n<ol>\n<li>The User navigates to a Service Provider (SP) — aka., Relying Party (RP)</li>\n<li>As the user requests to authenticate, the SP requests the browser through FedCM API to initiate authentication.</li>\n<li>The browser displays a list of available identity providers (supported by the RP), such as social IdPs like Google, Apple, LinkedIn, and Facebook, or other OAuth IdPs like LoginRadius.</li>\n<li>Once the user selects an IdP, the browser communicates with the IdP. Upon valid authentication, the IdP generates a secure token.\nThe browser delivers this secure token to the RP to facilitate user authorization.</li>\n</ol>\n<p>You can access a user demo of FedCM here: <a href=\"https://fedcm-rp-demo.glitch.me/\">FedCM</a>. </p>\n<p>For more information about implementing federated SSO with FedCM API, go through the <a href=\"https://developers.google.com/privacy-sandbox/3pcd/fedcm-developer-guide\">FedCM developer guide</a>.</p>\n<h2 id=\"how-is-loginradius-preparing-for-the-third-party-cookie-phase-out\" style=\"position:relative;\"><a href=\"#how-is-loginradius-preparing-for-the-third-party-cookie-phase-out\" aria-label=\"how is loginradius preparing for the third party cookie phase out permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How is LoginRadius Preparing for the Third-party Cookie Phase-out?</h2>\n<p>Firstly, we’re committed to solving our customers' user identity pain points — and preparing for the third-party cookies phase-out is no different.</p>\n<p>We’ll implement the most relevant and widely useful solutions to facilitate a smooth transition for our customers.</p>\n<p>Please subscribe to our blog for more information. We’ll update you on how we help with the third-party cookie phase-out.</p>\n<h2 id=\"in-conclusion\" style=\"position:relative;\"><a href=\"#in-conclusion\" aria-label=\"in conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>In Conclusion</h2>\n<p>The proposed changes to phase out third-party cookies and suggested alternatives are evolving as Google has been actively collaborating and discussing changes with the border community.</p>\n<p>Moreover, browsers like Firefox, Safari, and Edge may approach restricting third-party cookies differently than Google does.</p>\n<p>From LoginRadius, we’ll keep you updated on what we’re doing as a leading Customer Identity and Access Management (CIAM) vendor to prepare for the third-party cookie phase-out.</p>\n<h2 id=\"glossary\" style=\"position:relative;\"><a href=\"#glossary\" aria-label=\"glossary permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Glossary</h2>\n<p><strong>Top-level site</strong>: It is the primary site a user has visited.</p>\n<p><strong>First-party cookie</strong>: A cookie set by the top-level site.</p>\n<p><strong>Third-party cookie</strong>: A cookie set by a domain other than the top-level site. For example, let’s assume that a user has visited <code>a.com</code>, which might use an embed from <code>loginradius.com</code> to facilitate authentication. If <code>loginradius.com</code> sets a cookie when the user visits <code>a.com</code>, it is called a third-party cookie as the user hasn’t directly visited <code>loginradius.com</code>.</p>\n<h2 id=\"references\" style=\"position:relative;\"><a href=\"#references\" aria-label=\"references permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>References</h2>\n<ul>\n<li><a href=\"https://developers.google.com/privacy-sandbox/3pcd/prepare/prepare-for-phaseout\">Changes to Chrome's treatment of third-party cookies</a></li>\n<li><a href=\"https://developers.google.com/privacy-sandbox/3pcd/guides/identity\">Check the impact of the third-party cookie changes on your sign-in workflows</a></li>\n</ul>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"July 08, 2024","updated_date":null,"description":"Google Chrome has planned to phase out third-party cookies, which will affect different website functionalities depending on third-party cookies. This blog focuses on how this phase-out affects identity and user authentication and discusses alternatives for overcoming challenges.","title":"How Chrome’s Third-Party Cookie Restrictions Affect User Authentication?","tags":["Identity","Cookies","Chrome"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/eb7396060c0adc430dbed2d04b63d431/ee604/third-party-cookies-phaseout-chrome.png","srcSet":"/static/eb7396060c0adc430dbed2d04b63d431/69585/third-party-cookies-phaseout-chrome.png 200w,\n/static/eb7396060c0adc430dbed2d04b63d431/497c6/third-party-cookies-phaseout-chrome.png 400w,\n/static/eb7396060c0adc430dbed2d04b63d431/ee604/third-party-cookies-phaseout-chrome.png 800w,\n/static/eb7396060c0adc430dbed2d04b63d431/f3583/third-party-cookies-phaseout-chrome.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Raghunath Reddy","github":"raghunath-r-a","avatar":null}}}},"pageContext":{"limit":6,"skip":288,"currentPage":49,"type":"//engineering//","numPages":52,"pinned":"17fa0d7b-34c8-51c4-b047-df5e2bbaeedb"}},"staticQueryHashes":["1171199041","1384082988","2100481360","23180105","528864852"]}