Search Results for: Shopify

Shopify Development – Learn Shopify Liquid Programming

Do you want to learn Liquid programming so that you can customize or understand the codes of your Shopify theme? If yes, then you have come to the right place!

Welcome to the Shopify Liquid Programming course! In this course, my goal is to help you understand what is Liquid like what it does, and how to use it.

We’re going to cover the following features of Liquid:

  • Objects
  • Tags
  • Filters

If you are a Shopify store owner, and you’d like to understand how a Shopify store is running, then learning Liquid can be extremely helpful.

One of the biggest mistakes that people make is that they customize their Shopify theme aimlessly. What they usually do is Google the features that they’re looking for, then they will copy a code from someone else and apply it to their Shopify store without understanding the code that they copied and pasted.

This can be an issue since they don’t understand the objects, tags, and filters.

That’s why I’m here to help you avoid making that mistake!

Now, what are the things that you need to know before taking this course?

To get the best experience out of this course, it’s highly recommended that you know how to use Shopify.

What I mean is, you should know your way around Shopify from admin, to settings and to storefront.

Next, it’s important that you know at least the basics of programming (Like the operators, or data types). Though I will do my best to explain what is going on in each lessons so that even if you have less knowledge about programming, you’ll be able to understand the code.

In addition, for each lessons, I will provide resources related to the lessons (e.g. PDFs or articles) so that you can use those resources to learn more about Liquid.

Another thing that you can do is to post questions in the QnA section. So if you have questions, you can post them in the QnA.

I will also include in this course, quizzes or questionnaires so that you can test yourself if you can finally use Liquid.

So are you ready to learn Liquid? If yes, join me and I will see you on the other side.

How To Create FAQ Sections in Shopify (Online Store 2.0)

We’ve recently learned how to create an FAQ page for online store 2.0. Now, let’s learn how to make an FAQ section that you can reuse as many as wish.

Video Tutorial

If you prefer to watch video tutorials, you may watch the video version of this article instead.

Getting Started

Before we start this tutorial, we would like to mention that we will be using the free Shopify theme Dawn created by Shopify. If you’re using a different Shopify theme, don’t be surprised that yours are going to look different from mine. So if you’re having issues with your accordions, that may be because of your Shopify theme and its CSS.

Let’s begin this tutorial, by opening your theme’s code editor.

Go to Online Store and Themes.

Then, in the card of your Shopify theme of choice, click the Actions button and select Edit code.

This should open the code editor of your Shopify theme. Now, it’s time to make the section!

Creating The FAQ Section

For this FAQ section, we’re going to need two (2) files: sections/faq.liquid and assets/faq-style.css.

Let’s start with the stylesheet.

Open the assets folder and create a new asset and name it faq-style and make sure its extension is .CSS.

Once the file is created, copy the following code:

.faq-description {
  margin-top: 2em;
  margin-bottom: 2em;
}

.faq-checkbox {
  position: absolute;
  opacity: 0;
  z-index: -1;
}

.tabs {
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0px 0px 12px #4141416e;
}

.tab {
  width: 100%;
  color: white;
  overflow: hidden;
}

.tab-label {
  width: 100%;
  display: flex;
  justify-content: space-between;
  padding: 1em;
  font-weight: bold;
  color: white;
}	

.tab-content {
  max-height: 0;
  padding: 0 1em;
  background-color: white;
  transition: all 0.5s ease;
  color: black;
}

.tab-content p {
  margin: 0; 
}

.faq-checkbox:checked ~ .tab-content {
  max-height: 100vh;
  padding: 1em;
}
Code language: CSS (css)

Save the file.

Next, let’s create the sections/faq.liquid.

Open the sections folder and create a new section file and name it faq. Then, copy the following code:

<link rel="stylesheet" href="{{ 'faq-style.css' | asset_url }}" media="print" onload="this.media='all'">

<div class="page-width page-width--narrow">
  <div class="faq-container">
    <div class="tabs">
    	{% for block in section.blocks %}
      		{% assign item = block.settings %}
      		
      		<div class="tab">
      			<input type="checkbox" id="faq_checkbox_{{ forloop.index }}" class="faq-checkbox">
        		<label for="faq_checkbox_{{ forloop.index }}" class="tab-label button button--primary">{{ item.question }}</label>
        		<div class="tab-content">{{ item.answer }}</div>
      		</div>
      	{% endfor %}
    </div>
  </div>
</div>

{% schema %}
{
	"name": "FAQ",
	"tag": "section",
	"class": "spaced-section",
	"blocks": [
		{
			"name": "FAQ Item",
			"type": "faq",
			"settings": [
				{
					"type": "text",
					"id": "question",
					"label": "Question",
					"default": "Do you have a question?"
				},
				{
					"type": "richtext",
					"id": "answer",
					"label": "Answer",
					"default": "<p>I have an answer</p>"
				}
			]
		}
	],
	"presets": [
		{ "name": "FAQ Block" }
	]
}
{% endschema %}
Code language: HTML, XML (xml)

Now, if you open your theme editor, you should be able to add FAQ blocks by clicking the Add section button like below

Now, if you wish to add titles and descriptions to your FAQ blocks, you can update your faq.liquid to the following code.

<link rel="stylesheet" href="{{ 'faq-style.css' | asset_url }}" media="print" onload="this.media='all'">

<div class="page-width page-width--narrow">
  <h1 class="main-page-title page-title h0">
    {{ section.settings.faq_title | escape }}
  </h1>
  
  {% if section.settings.faq_description %}
    <div class="rte faq-description">
      {{ section.settings.faq_description }}
    </div>
  {% endif %}
  
  <div class="faq-container">
    <div class="tabs">
    	{% for block in section.blocks %}
      		{% assign item = block.settings %}
      		
      		<div class="tab">
      			<input type="checkbox" id="faq_checkbox_{{ forloop.index }}" class="faq-checkbox">
        		<label for="faq_checkbox_{{ forloop.index }}" class="tab-label button button--primary">{{ item.question }}</label>
        		<div class="tab-content">{{ item.answer }}</div>
      		</div>
      	{% endfor %}
    </div>
  </div>
</div>

{% schema %}
{
	"name": "FAQ",
	"tag": "section",
	"class": "spaced-section",
	"settings": [ 
		{
			"type": "text",
			"id": "faq_title",
			"default": "Frequently Asked Questions",
			"label": "Title"
		},
		{
			"type": "text",
			"id": "faq_description",
			"default": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
			"label": "Description"
		}
	],
	"blocks": [
		{
			"name": "FAQ Item",
			"type": "faq",
			"settings": [
				{
					"type": "text",
					"id": "question",
					"label": "Question",
					"default": "Do you have a question?"
				},
				{
					"type": "richtext",
					"id": "answer",
					"label": "Answer",
					"default": "<p>I have an answer</p>"
				}
			]
		}
	],
	"presets": [
		{ "name": "FAQ Block" }
	]
}
{% endschema %}
Code language: HTML, XML (xml)

If you save your files, you should be able to create as many FAQ blocks as your want!

Conclusion

There you have it! You just created FAQ blocks using sections. Now, you will be able to create accordions everywhere you want as long as the template file is using sections. There are a few problems in this accordion though, specifically, the styling of it. In this project, we haven’t used any styling for the buttons and its label so if your Shopify theme is using bright colors for buttons, the label of this accordion will not be that visible so you may have to tweak the styling a bit if you encounter the said issue. Other than that, that’s pretty much it.

Shopify Theme Development: Online Store 2.0 + TailwindCSS

Shopify just recently updated their Shopify online experience and now they call it “Online Store 2.0”.

With this update, Shopify merchants can now customize their entire online store using sections & blocks. This opened a lot of doors not just for Shopify app developers but also for Shopify theme developers because now, you can add cool sections and blocks to the most commonly used pages like products page, collections page, blog page, etc. If you’re a Shopify theme developer and you don’t know yet how to create a Shopify theme for Online Store 2.0, then this is the best time to learn because Shopify is now accepting Shopify themes to be listed on their Shopify Theme Store! This means you can make money by selling your Shopify themes! So are you interested to learn more? In this course, we’re going to learn how to create a Shopify theme for Online Store 2.0 using Shopify CLI with the help of TailwindCSS to design a cool online store. In this course you will learn:
  1. How to set up your development store using Shopify CLI 3.0
  2. Using TailwindCSS to design a Shopify theme
    • Create navigational bar
    • Create collection page
    • Create product page
    • Create customer page
    • Create cart page
    • and more!
  3. Online Store 2.0 (JSON Templates)
  4. Shopify CLI
  5. Shopify GitHub Integration
  6. Schema Settings
  7. Search Engine Optimization (SEO) for pages like articles, products, etc.
  8. Liquid language (Referencing asset files, loops, conditional statements, Shopify objects, filters, and many more)
  9. Customer Templates
If you think you’re ready to start, signup now, and let’s create the best Shopify theme together!

Shopify App Development in Vanilla PHP: Creating Products w/ GraphQL

Over the past few years, REST has become the only way for designing web APIs. However, there are things that make REST very inflexible. For example, you cannot control how much data you can retrieve or you can’t specify the only data that you wish to retrieve, etc.

This happens in Shopify app development as well. If you want to get a product using REST API, all of the data about your products will be sent to you. This makes REST very heavy and slow to use.

So, that’s why GraphQL was created, to cope with the need for more flexibility and efficiency.

But, we’re not going to focus on the difference between REST and GraphQL. Instead, we’re going to learn how to create products using GraphQL mutations and vanilla PHP.

Video Tutorial

If you prefer watching video tutorials, then the video below is for you.

Otherwise, feel free to keep reading the content below.

Getting Started

If this is your first time learning how to make Shopify apps using vanilla PHP, then we highly recommend reading through our guide here. We also have a ton of videos covering Shopify app development, so before you proceed, make sure that you have a local web server and a Shopify app installed in your development store.

Before we start using GraphQL mutations in PHP, we need to create a function that will allow us to make API calls.

GraphQL API Call Function

Create a new PHP file called functions.php and copy the following code:

<?php


function graphql($token, $shop, $query = array()) {
	$url = "https://" . $shop . "/admin/api/2021-07/graphql.json";

	$curl = curl_init($url);
	curl_setopt($curl, CURLOPT_HEADER, TRUE);
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
	curl_setopt($curl, CURLOPT_FOLLOWLOCATION, TRUE);
	curl_setopt($curl, CURLOPT_MAXREDIRS, 3);
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);


	$request_headers[] = "";
	$request_headers[] = "Content-Type: application/json";
	if (!is_null($token)) $request_headers[] = "X-Shopify-Access-Token: " . $token;
	curl_setopt($curl, CURLOPT_HTTPHEADER, $request_headers);
	curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($query));
	curl_setopt($curl, CURLOPT_POST, true);

	$response = curl_exec($curl);
	$error_number = curl_errno($curl);
	$error_message = curl_error($curl);
	curl_close($curl);

	if ($error_number) {
		return $error_message;
	} else {

		$response = preg_split("/\r\n\r\n|\n\n|\r\r/", $response, 2);

		$headers = array();
		$header_data = explode("\n",$response[0]);
		$headers['status'] = $header_data[0]; 
		array_shift($header_data);
		foreach($header_data as $part) {
			$h = explode(":", $part, 2);
			$headers[trim($h[0])] = trim($h[1]);
		}

		return array('headers' => $headers, 'body' => $response[1]);

	}
    
}
Code language: PHP (php)

This function above will allow you to send GraphQL queries to the Shopify GraphQL endpoint. You just need to provide your access token, Shopify store domain, and the query/mutation.

Alright, so now that we have the function to make GraphQL API calls, we can start and set up our index file.

The Index File

Create a new PHP file in your project and make sure it’s your index file so name it index.php. Once the file is created, you can copy the following code:

<?php
require_once( "functions.php" );
$shop_url = $_GET['shop'];
$access_token = 'shpca_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

?>
Code language: PHP (php)

In the code above, we referenced the functions.php so that we can use the graphql() function.

Now, make sure that you have your access token in the $access_token variable. If you don’t know how to generate an access token, then watch our tutorial here.

Let’s assume you already have your access token, we can now proceed and use the GraphQL function to create products.

Creating Products using GraphQL Mutations

In the same file, create a new variable and use the function graphql() like what we did below.

<?php
require_once( "inc/functions.php" );
$shop_url = $_GET['shop'];
$access_token = 'shpca_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

$mutation = graphql($access_token, $shop_url, array());
?>
Code language: PHP (php)

In the 3rd argument, we applied an empty array, that array is where you’re going to apply the query/mutation.

So let’s create a new variable and call it $query or whatever you want. Then, in this variable, we will create an array and its key SHOULD be set to query. Again, the key SHOULD be set to query and not something else. Then, we’re going to use that variable in the 3rd argument of the graphql() function.

<?php
require_once( "inc/functions.php" );
$shop_url = $_GET['shop'];
$access_token = 'shpca_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

$query = array("query" => '');
$mutation = graphql($access_token, $shop_url, $query);
?>
Code language: PHP (php)

Next, let’s use mutations.

Update the array to the following:

<?php
require_once( "inc/functions.php" );
$shop_url = $_GET['shop'];
$access_token = 'shpca_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

$query = array("query" => '
	mutation {
		productCreate(
			input: {
				title: "Vanilla PHP & GraphQL"
				descriptionHtml: "<p>I am created using GraphQL!</p>"
			}
		) {
			product {
				id
				title
			}
		}
	}
');

$mutation = graphql($access_token, $shop_url, $query);
?>
Code language: PHP (php)

In this mutation, we used the productCreate field and this field requires us to provide an argument input so there we provided a title and a descriptionHtml. After the product is created, the mutation will then return a field called product and in that field, we create retrieve data about the product like its id, title, tags, images, etc. To learn more about the product field, click here.

That’s it! If you run your app, it should give you the following response.

{
	"data": {
		"productCreate": {
			"product": {
				"id": "gid:\/\/shopify\/Product\/1234567890"
				"title": "Vanilla PHP & GraphQL"
			}
		}
	}
}
Code language: JSON / JSON with Comments (json)

How To Paginate Shopify Products with Product REST API

So you have finally learned how to display products using Shopify Product REST API. However, you have a bit of a problem, you want to display products with pagination and the only thing you think you can do is to create an array of products and display them depending on their keys.

Believe it or not, it’s not actually a bad idea but offers a TON of work.

Shopify Product API (version 2021-07 and beyond) provides a link header that you can use for requesting paginated REST Admin API endpoints and that’s what we’re going to learn today.

Keep in mind that before proceeding, you must know already how to use Shopify API or you have created a Shopify app using our Shopify app development tutorial.

If in case this is your first time, we highly suggest you read our tutorial below.

Read more: How To Create Shopify Apps from Scratch

Video Tutorial

If you prefer watching video tutorials, you can watch the video version of this article here:

Getting Started

Before you can create pagination, it’s important to understand that this will only work for API version 2021-01 and beyond. So if you’re using an old version of the API, then we highly recommend you to go to your app settings and update your API version.

Another important thing is to understand how the product API works. By default, you can return up to 50 products per page but you can also maximize the number up to 250 products.

Each page will provide you a set of links (aka. page info) in the header that you can use to go to the next or previous set of items.

To properly explain this… Let’s say we have 200 products, and we want to display 10 products per page.

If we are on the very first page of our products, the API will give us just one link in the header, for us to be able to go to the next page.

If we are on the second page, the API will give us two links in the header, one for the previous page and one for the next page.

And so on, and so forth.

REST API Function

If this is your first time working with PHP, keep in mind that we are using the following functions.php. In this PHP file, we have a function that allows us to do API calls. So if you don’t have this function, you won’t be able to get products from Shopify API.

<?php
function rest_api($token, $shop, $api_endpoint, $query = array(), $method = 'GET', $request_headers = array()) {
	$url = "https://" . $shop . $api_endpoint;
	if (!is_null($query) && in_array($method, array('GET', 	'DELETE'))) $url = $url . "?" . http_build_query($query);

	$curl = curl_init($url);
	curl_setopt($curl, CURLOPT_HEADER, TRUE);
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
	curl_setopt($curl, CURLOPT_FOLLOWLOCATION, TRUE);
	curl_setopt($curl, CURLOPT_MAXREDIRS, 3);
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
	curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30);
	curl_setopt($curl, CURLOPT_TIMEOUT, 30);
	curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);

	$request_headers[] = "";
	$headers[] = "Content-Type: application/json";
	if (!is_null($token)) $request_headers[] = "X-Shopify-Access-Token: " . $token;
	curl_setopt($curl, CURLOPT_HTTPHEADER, $request_headers);

	if ($method != 'GET' && in_array($method, array('POST', 'PUT'))) {
		if (is_array($query)) $query = json_encode($query);
		curl_setopt ($curl, CURLOPT_POSTFIELDS, $query);
	}
    
	$response = curl_exec($curl);
	$error_number = curl_errno($curl);
	$error_message = curl_error($curl);
	curl_close($curl);

	if ($error_number) {
		return $error_message;
	} else {

		$response = preg_split("/\r\n\r\n|\n\n|\r\r/", $response, 2);
		$headers = array();
		$header_data = explode("\n",$response[0]);
		$headers['status'] = $header_data[0];
		array_shift($header_data);
		foreach($header_data as $part) {
			$h = explode(":", $part);
			$headers[trim($h[0])] = trim($h[1]);
		}

		return array('headers' => $headers, 'data' => $response[1]);

	}
    
}Code language: HTML, XML (xml)

Displaying Products

If you have been following us for a while, then you probably know already how to display Shopify products using PHP and Shopify API.

Let’s say we have the following code:

<?php
require_once("inc/functions.php");

$shop_url = $_GET['shop'];
$access_token = 'shpca_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

$products = rest_api($access_token, $shop_url, "/admin/api/2021-07/products.json", array(), 'GET');
$products = json_decode($products['data'], true);

?>

<!DOCTYPE html>
<html>
<head>
	<title>Shopify Example App</title>
</head>
<body>
	<div>
		<ul id="product-list">
			<?php
				foreach($products as $product){ 
				    foreach($product as $key => $value){ 
						echo '<li>' . $value['title'] . '</li>';
				    }
				}
			?>
		</ul>
	</div>
</body>
</html>
Code language: HTML, XML (xml)

The code above will simply display all the products you have in your store like below.

Displaying all products with Shopify Product API

In total, we have 27 products.

Now, the next thing that we’re going to do is to make limitations for our API. Let’s say we just want to display 5 products per page.

To do that, we need to create an array where we indicate how many items we want to display using the parameter limit.

$array = array(
			'limit' => 5
		);
$products = rest_api($access_token, $shop_url, "/admin/api/2021-07/products.json", $array, 'GET');
$products = json_decode($products['data'], true);
Code language: PHP (php)
Shopify Product API limit parameter

Awesome! Now we’re just displaying the first 5 products.

Previous & Next Buttons

Now that we have successfully displayed and limit our products. Let’s create the buttons that we’re going to use to navigate to the next page (…and also the previous page of course).

Just underneath your unordered list element, add the following code.

<button type="button" data-info="" data-rel="previous" data-store="<?php echo $shop_url; ?>">Previous</button>
<button type="button" data-info="" data-rel="next" data-store="<?php echo $shop_url; ?>">Next</button>

Code language: HTML, XML (xml)
Shopify Product Pagination API previous and next buttons

Awesome!

Updating functions.php

If you’re using the same function that we used for developing Shopify apps, then you’ll most likely encounter the very same bug that we experience whenever we use the rest_api() function.

If you use the said function just for the sake of returning Shopify’s response, then you might think that there’s no problem at all.

However, when you use the function to get headers, specifically for making pagination. You will notice that there’s something wrong/missing and that is the link header.

Shopify API getting the link in the header for pagination

The main reason why that’s happening is because of the ‘colons’ in the header.

The functions.php file is simply using the explode() function to create an array for the header. Then loop through each key in the array, and explode once again with the help of colon this time. That’s also where the issue starts to develop.

Since URLs have their own colon (https://), the function explode will obviously malfunction.

So with all that being said, let’s update our functions.php.

Look for the following lines of code:

foreach($header_data as $part) {
	$h = explode(":", $part);
	$headers[trim($h[0])] = trim($h[1]);
}
Code language: PHP (php)

and change it to…

foreach($header_data as $part) {
	$h = explode(":", $part, 2);
	$headers[trim($h[0])] = trim($h[1]);
}
Code language: PHP (php)

The file functions.php is located in inc folder.

Very simple, we only have to add a limit to our explode function. If the explode function hits the first separator, it should end the process.

Now let’s go back to our index file and update the following code:

$array = array(
			'limit' => 5
		);
$products = rest_api($access_token, $shop_url, "/admin/api/2021-07/products.json", $array, 'GET');
$products = json_decode($products['data'], true);
Code language: PHP (php)

to…

$array = array(
			'limit' => 5
		);
$products = rest_api($access_token, $shop_url, "/admin/api/2021-07/products.json", $array, 'GET');

$headers = $products['headers'];

$products = json_decode($products['data'], true);

foreach ($headers as $key => $value) {
	echo '<div>[' . $key . '] =>' . $value . '</div>';
}
Code language: PHP (php)

In the code above, we simply created a new variable and retrieved the headers.

And then underneath the $products variable, we check each value inside the $headers variable using foreach function

You should have the following output.

Shopify header response for link and product pagination

If you look closely, you can clearly see that the link key only a value of ; rel="next".

That’s because the rest of its value is being converted to an HTML tag instead of a string.

So if you go to your inspector, you will see that everything was enclosed with the <https></https> tag.

Shopify Header API link header being HTML

To solve that issue, we need to create our own function to extract the string between the angle brackets.

So open your functions.php file once again and just underneath your rest_api() function, add the following code.

//shopify_call() { ... } <--- make sure you add the code outside this function

function str_btwn($string, $start, $end){
    $string = ' ' . $string;
    $ini = strpos($string, $start);
    if ($ini == 0) return '';
    $ini += strlen($start);
    $len = strpos($string, $end, $ini) - $ini;
    return substr($string, $ini, $len);
}
Code language: PHP (php)

Going back to index.php file. And just underneath the foreach() function, add the following code.

$nextPageURL = str_btwn($headers['link'], '<', '>');
$nextPageURLparam = parse_url($nextPageURL); 
parse_str($nextPageURLparam['query'], $value);
$page_info = $value['page_info'];
Code language: PHP (php)

Next, we’ll update our Next button’s data-info attribute from.

<button type="button" data-info="" data-rel="next" data-store="<?php echo $shop_url; ?>">Next</button>
Code language: HTML, XML (xml)

to…

<button type="button" data-info="<?php echo $page_info; ?>" data-rel="next" data-store="<?php echo $shop_url; ?>">Next</button>
Code language: HTML, XML (xml)

Scripting Shopify Pagination with AJAX

We basically got everything we need to display our products and pagination. Now let’s work with AJAX so we can retrieve the next and previous products.

Just before your body closing tag, add the following code.

<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
    $('button').on('click', function(e) {
      var data_info = $(this).attr('data-info');
      var data_rel = $(this).attr('data-rel');
      var data_store = $(this).attr('data-store');

      if(data_info != '') {
        $.ajax({
          type: "GET",
          url: "pagination.php", 
          data: {
            page_info: data_info,
            rel: data_rel,
            url: data_store
          },           
          dataType: "json",               
          success: function(response) {
            console.log(response);

            if( response['prev'] != '' ) {
              $('button[data-rel="previous"]').attr('data-info', response['prev']);
            } else {
              $('button[data-rel="previous"]').attr('data-info', "");
            }

            if( response['next'] != '' ) {
              $('button[data-rel="next"]').attr('data-info', response['next']);
            } else {
              $('button[data-rel="next"]').attr('data-info', "");
            }

            if( response['html'] != '' ) {
              $('#product-list').html(response['html']);
            }
          }
        });
      }

    });
</script>
Code language: HTML, XML (xml)

Don’t forget to save your files.

The Pagination Script

Now that we have finally programmed our index file, let’s create a new PHP script for our AJAX. Of course, we’ll call it pagination.php.

<?php
require_once("inc/functions.php");

$shop_url = $_GET['shop'];
$access_token = 'shpca_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

$rel = $_GET['rel'];
$page_info = $_GET['page_info'];
Code language: HTML, XML (xml)

First of all, we need to get everything that we need such as our access token, our shop subdomain, and the data values that we passed through AJAX.

Next, we’ll create the API. So just underneath the code, add the following:

//Create an array for the API
$array = array(
		'limit' => 5,
		'page_info' => $page_info,
		'rel' => $rel
	);

$products = rest_api($access_token, $shop_url, "/admin/api/2021-07/products.json", $array, 'GET');
Code language: PHP (php)

Next, we’ll create everything we need for our headers, check if the link header contains two page_infos, otherwise retrieve the default value.

//Get the headers
$headers = $products['headers'];

//Create an array for link header
$link_array = array();

//Check if there's more than one links / page infos. Otherwise, get the one and only link provided
if( strpos( $headers['link'], ',' )  !== false ) {
	$link_array = explode(',', $headers['link'] );
} else {
	$link = $headers['link'];
}
Code language: PHP (php)

Next, we’ll create another set of variables and check if the $link_array count is greater than one. If it is, then we take the two page_infos from each link array. Otherwise, just get what’s provided.

//Create variables for the new page infos
$prev_link = '';
$next_link = '';

//Check if the $link_array variable's size is more than one
if( sizeof( $link_array ) > 1 ) {
    $prev_link = $link_array[0];
    $prev_link = str_btwn($prev_link, '<', '>');

    $param = parse_url($prev_link); 
    parse_str($param['query'], $prev_link); 
    $prev_link = $prev_link['page_info'];

    $next_link = $link_array[1];
    $next_link = str_btwn($next_link, '<', '>');

    $param = parse_url($next_link); 
    parse_str($param['query'], $next_link); 

    $next_link = $next_link['page_info'];
} else {
    $rel = explode(";", $headers['link']);
    $rel = str_btwn($rel[1], '"', '"');

    if($rel == "previous") {
        $prev_link = $link;
        $prev_link = str_btwn($prev_link, '<', '>');

        $param = parse_url($prev_link); 
        parse_str($param['query'], $prev_link); 

        $prev_link = $prev_link['page_info'];

        $next_link = "";
    } else {
        $next_link = $link;
        $next_link = str_btwn($next_link, '<', '>');

        $param = parse_url($next_link); 
        parse_str($param['query'], $next_link); 

        $next_link = $next_link['page_info'];

        $prev_link = "";
    }
}
Code language: PHP (php)

And last but not least, we’ll create the variable for our frontend to display the next set of products.

//Create and loop through the next or previous products
$html = '';

$products = json_decode($products['data'], true);

foreach($products as $product) { 
    foreach($product as $key => $value) { 
		$html .= '<li>' . $value['title'] . '</li>';
    }
}
Code language: PHP (php)

Seriously though, this is the last…

Let’s encode everything into JSON and pass it back to AJAX.

//Then we return the values back to ajax
echo json_encode( array( 'prev' => $prev_link, 'next' => $next_link, 'html' => $html ) );
Code language: PHP (php)

Save all your files and you should have the following output.

Conclusion

If you have reached this part then good job! You have successfully learned how to create pagination for your Product API. Obviously, there are plenty of other ways to do this but this tutorial is just to give you an idea that it is possible to make paginations for products.

If you have concerns or questions, don’t hesitate to let us know in the comments below!

How To Migrate Shopify Themes to Online Store 2.0 (JSON Templates)

Let’s say you have a Shopify store and you’ve been working on it for years. Then, after some time, you’ve taken a look at your Shopify homepage and you’ve decided to customize your Shopify store for a little bit.

But then, BOOM!

You’ve found out that Shopify just recently changed the look of the customizer page and now, you’re lost. So you started reading about it and then you’ve realized that there are new features that you can do.

But, unfortunately, it looks like you can’t do any of the new features (like the “modularity” of the entire Shopify store, app blocks or app extensions, etc.) and that’s because you’re using an old Shopify theme and you need to upgrade it to a JSON template.

So, how can you upgrade your Shopify theme?

Well, in this article we are going to learn how to migrate a Shopify theme from Liquid to Online Store 2.0 (aka JSON templates).

Video Tutorial

If you prefer watching video tutorials, you can watch the following video version of this article.

Otherwise, you can continue below.

Getting Started

Before we get started, I want to point out that we are going to use Debut as an example in this article. We are also going to ONLY show you how to migrate a single template file from Liquid to JSON template and so if you’re looking for an in-depth tutorial about migrating all of the template files to JSON, I highly recommend taking the Shopify Theme Development course. In that course, I will be covering all of the template files from 404 to Search template file.

Also, before we begin, make sure that you BACKUP your Shopify theme. There are a lot of ways to backup a Shopify theme so make sure you do that before doing any of the steps that I will be mentioning in this article.

Migrating Shopify Themes to JSON Templates

You can migrate a Shopify theme in 5 simple steps:

  • Identify the sections of your theme templates
  • Replace the Liquid template with JSON template
  • Test your theme

Looks very simple no? Well, let’s see how to do them.

1. Identify the sections of your Shopify theme templates

Before you can start migrating your template files to a JSON template, you need to make sure that all of the {% section %} tags inside of a template are removed. This is because Shopify doesn’t allow you anymore to use the {% section %} tag inside of a section file and by using a {% section %} tag in a section file, you will receive the following error:

Liquid error (section/section-example.liquid line 58): Cannot render sections inside sections

Once you have found a section tag inside of your section, you have two options:

  1. Move the code of that section to the section referencing that section. (Might be confusing)
  2. Create a layout that reference that section.

The second option is quite advanced so to make this article shorter and simple, we’ll just do the first option and so that you get what I’m trying to say in that list.

  1. Open your theme code editor
  2. Locate a template file (They’re usually inside of the /templates directory). Let’s use the article.liquid in this tutorial.
  3. Search for {% section %} tags. (If this is your first time opening that template file, you should be able to find a section tag that references the section named “article-template”).

    Did you find one? Great. Remove that section tag and open that “article-template” section file.
    Inside of that section file, you should see a part of the article template that renders the blog post.

    So what you’re going to do is to move all of that code to the article.liquid. Because the whole point is to remove all of the section tags from your template.

    Now, keep in mind that you should move or paste the code of the “article-template” to the line where the {% section %} tag is located. So if the section tag is located in line 17, then you should paste the code of that section in line 17.
  4. Do the same steps for the rest of the section tags that you find.

2. Replace the old template with JSON template

Now that we have removed the section tags from our template file, we can finally replace this template file with JSON template. But first, we need to move the code of the article.liquid to a section file and then, we can delete the article.liquid and replace it with article.json.

  1. Go to /sections directory or folder and create a new section. Name it whatever you what but make sure you remember this name because we’ll use this name in the article JSON template file.
    In my case, I’ll name it template-article.
  2. Inside of the template-article.liquid, I’ll move ALL of the code from the article.liquid template file.
  3. Delete the article.liquid.
  4. Go to /templates directory or folder and create a new template file and select article and make sure that you select JSON instead of Liquid.
  5. Once the article.json is created, replace its code with the following:
{
 "sections": {
   "template": {
     "type": "template-article"
   }
 },
 "order": ["template"]
}Code language: JSON / JSON with Comments (json)

Save the file.

3. Test your Shopify theme.

Once you have created your new template, open it with the customizer and check if you can add sections to your article template. If you can, then that means you have successfully migrated your template file from Liquid to JSON template.

Now the next thing that you’re going to do is to apply the same steps to the rest of the template files.

Conclusion

Migrating your Shopify themes from the old template system to Online Store 2.0 is honestly very easy, but it can be very difficult depending on what Shopify theme you’re about to migrate. So my advice, especially if you’re using a different theme, is to learn your Shopify theme first, back it up, and use it with a development store or a test store. That way, your Shopify store is safe from being broken.

We haven’t covered in this article how to use app blocks in JSON template so we’ll probably just cover them in the next video of our YouTube channel. So, if you’re interested, make sure you subscribe to our YouTube channel so we can notify you when we upload a new lesson.

Shopify App Development – Vanilla PHP, GraphQL, App Bridge & REST API

This course is last updated on September 07, 2023

When you wish to learn to program, the first thing most coders think of is to learn Python, C++, WordPress, or WooCommerce. But all of these languages and platforms are already saturated. That’s why if you learn them, you’ll most likely end up not getting a profit.

So, instead of making WordPress or other stuff, why not start making Shopify apps? Like what Shopify said, “There’s never been a better time to build a Shopify app because there are more than 1.8 million merchants across the globe that build, scale, and manage their businesses on Shopify”.

If you don’t know, Shopify apps play an important role in every Shopify store’s success. In fact, it is SO important that every Shopify store uses an average of SIX Shopify apps.

So why not start making Shopify apps?

💸 Imagine making thousands of 💵 dollars monthly with your very own Shopify app. Yes, MONTHLY! And the best part? Shopify won’t take a share of your app revenues. It’s all yours! 💰💰💰

🤩 Excited yet? You should be!

In this course, I’ll guide you through crafting a top-notch Shopify app from scratch, using vanilla PHP. No shortcuts, no pre-made repositories. We’re building it all from the ground up, ensuring you have the skills to create unique, high-demand Shopify apps.

👨‍💻 About me: I’ve been immersed in Shopify app development since 2018. Everything I’ve learned along the way, I’m sharing with YOU, so you can kickstart your new career and turn your Shopify apps into a lucrative venture.

Here is what you are going to learn in this course:

  • Creating API credentials
  • Understanding API and secret keys
  • Creating a local server and tunnel
  • Connect your Shopify app to the database
  • Creating Shopify OAuth
  • Generating access tokens
  • Creating REST API & GraphQL functions
  • Creating ScriptTags
  • Charging merchants with Billing API
  • Implementing Shopify App Bridge
  • and much more!

If you think you’re ready to start a new career then join us and let’s begin creating YOUR very first Shopify app!

Changelog

September 07, 2023

  • Updated course description

April 28, 2022

  • Added/Updated lessons
  • Added resource(s)

September 29, 2021

  • Added/Updated lessons

September 21, 2021

  • Updated links and resources in contents

September 15, 2021

  • Added new lesson “Application Credit” on “Billing API

How To Create Easy Cart Drawers in Shopify (without Shopify apps)

So you have a Shopify store but you personally don’t like how you have to visit the cart page just to see the total amount you need to pay or to proceed to the checkout page. Well, in this article, we will be learning how to create an offset canvas or a cart drawer that displays the items inside of a Shopify store cart without installing Shopify apps.

Video Tutorial

If you prefer watching video tutorials rather than reading, then you can watch the video version of this article below:

Getting Started

Before we can start displaying the items from our cart, we, obviously, need to create the offset canvas or the drawer first. Now, I just want to make a shoutout to Tomasz Bujnowicz for making this amazing easy sliding drawer. So credits to him for making this lesson easier to accomplish.

Anyway, let’s begin! Open your Shopify store admin page and access your code editor.

Then, go to the assets folder and create two asset files:

  • drawer.css
  • drawer.js

Once you have created the two files, open them and apply the following codes:

Drawer.css

For the styles of the drawer, copy the following code:

.drawer {
  display: none;
}

.drawer__header {
  padding: 1.5rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid #ddd;
}

.drawer__close {
  margin: 0;
  padding: 0;
  border: none;
  background-color: transparent;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%0A%3Csvg width='15px' height='16px' viewBox='0 0 15 16' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cg id='Page-1' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cg id='2.-Menu' transform='translate(-15.000000, -13.000000)' stroke='%23000000'%3E%3Cg id='Group' transform='translate(15.000000, 13.521000)'%3E%3Cpath d='M0,0.479000129 L15,14.2971819' id='Path-3'%3E%3C/path%3E%3Cpath d='M0,14.7761821 L15,-1.24344979e-14' id='Path-3'%3E%3C/path%3E%3C/g%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
  width: 15px;
  height: 15px;
}

.drawer__wrapper {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  height: 100%;
  width: 100%;
  max-width: 500px;
  z-index: 9999;
  overflow: auto;
  transition: transform 0.3s;
  will-change: transform;
  background-color: #fff;
  display: flex;
  flex-direction: column;
  -webkit-transform: translateX(103%);
  transform: translateX(103%);
  -webkit-overflow-scrolling: touch;
  box-shadow: 0 2px 6px #777;
}

.drawer__content {
  position: relative;
  overflow-x: hidden;
  overflow-y: auto;
  height: 100%;
  flex-grow: 1;
  padding: 1.5rem;
}

.drawer.is-active {
  display: block;
}

.drawer.is-visible .drawer__wrapper {
  -webkit-transform: translateX(0);
  transform: translateX(0);
}

.drawer.is-visible .drawer__overlay {
  opacity: 0.5;
}

.drawer__overlay {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  z-index: 200;
  opacity: 0;
  transition: opacity 0.3s;
  will-change: opacity;
  background-color: #000;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
Code language: CSS (css)

Drawer.js

For the JavaScript of the drawer, copy the following code:

var drawer = function () {
    if (!Element.prototype.closest) {
      if (!Element.prototype.matches) {
        Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
      }
      Element.prototype.closest = function (s) {
        var el = this;
        var ancestor = this;
        if (!document.documentElement.contains(el)) return null;
        do {
          if (ancestor.matches(s)) return ancestor;
          ancestor = ancestor.parentElement;
        } while (ancestor !== null);
        return null;
      };
    }
    var settings = {
      speedOpen: 50,
      speedClose: 350,
      activeClass: 'is-active',
      visibleClass: 'is-visible',
      selectorTarget: '[data-drawer-target]',
      selectorTrigger: '[data-drawer-trigger]',
      selectorClose: '[data-drawer-close]',

    };


    var toggleccessibility = function (event) {
      if (event.getAttribute('aria-expanded') === 'true') {
        event.setAttribute('aria-expanded', false);
      } else {
        event.setAttribute('aria-expanded', true);
      }
    };


    var openDrawer = function (trigger) {
      var target = document.getElementById(trigger.getAttribute('aria-controls'));
      target.classList.add(settings.activeClass);
      document.documentElement.style.overflow = 'hidden';
      toggleccessibility(trigger);


      setTimeout(function () {
        target.classList.add(settings.visibleClass);
      }, settings.speedOpen);
    };

    var closeDrawer = function (event) {
      var closestParent = event.closest(settings.selectorTarget),
        childrenTrigger = document.querySelector('[aria-controls="' + closestParent.id + '"');
      closestParent.classList.remove(settings.visibleClass);
      document.documentElement.style.overflow = '';
      toggleccessibility(childrenTrigger);
      setTimeout(function () {
        closestParent.classList.remove(settings.activeClass);
      }, settings.speedClose);
    };
    var clickHandler = function (event) {
      var toggle = event.target,
        open = toggle.closest(settings.selectorTrigger),
        close = toggle.closest(settings.selectorClose);


      if (open) { openDrawer(open); }
      if (close) { closeDrawer(close); }
      if (open || close) { event.preventDefault(); }
    };


    var keydownHandler = function (event) {
      if (event.key === 'Escape' || event.keyCode === 27) {
        var drawers = document.querySelectorAll(settings.selectorTarget),
          i;
        for (i = 0; i < drawers.length; ++i) {
          if (drawers[i].classList.contains(settings.activeClass)) {
            closeDrawer(drawers[i]);
          }
        }
      }
    };

    document.addEventListener('click', clickHandler, false);
    document.addEventListener('keydown', keydownHandler, false);
};

drawer();
Code language: JavaScript (javascript)

Creating the cart drawer

Now that we finally have the style and the JavaScript code for our cart drawer, we can now create the HTML of the drawer.

Open your Shopify code editor once again and in the sections folder, create a new section file and name it drawer.liquid and apply the following code:

<section class="drawer" id="drawer-name" data-drawer-target>
  <div class="drawer__overlay" data-drawer-close tabindex="-1"></div>
  <div class="drawer__wrapper">
    <div class="drawer__header">
      <div class="drawer__title">
        Continue Shopping
      </div>
      <button class="drawer__close" data-drawer-close aria-label="Close Drawer"></button>
    </div>
    <div class="drawer__content" id="cart__drawer">
      <div id="cart__drawer_items">
      </div>
      <div style="margin-top: 50px">
        <h4>Total: <span id="cart__total_price"></span></h4>
        <a id="cart__checkout_btn" href="/checkout" class="btn btn--has-icon-after cart__continue-btn" style="width:100%;">Proceed Checkout</a>
      </div>
    </div>
  </div>
</section>


<script>
  fetch('/cart.js')
  .then((resp) => resp.json())
  .then((data) => {
    
    if(data.items.length > 0) {
        data.items.forEach(function(product, index) { 
          document.getElementById('drawer_cart_items').innerHTML = '<img src="' + product.featured_image.url + '" alt="' + product.featured_image.alt + '"><h5>' + product.title + '</h5><p>' + product.quantity + ' x ' + theme.Currency.formatMoney(product.line_price, theme.moneyFormat) + '</p>';
      	});
    } else {
      document.getElementById('drawer_cart_items').innerHTML = '<p>Cart is empty</p>';
      document.getElementById('drawer_checkout_btn').setAttribute('disabled', 'disabled');
      document.getElementById('drawer_checkout_btn').style.pointerEvents = 'none';
    }
    
    document.getElementById('drawer_total_amount').innerHTML = theme.Currency.formatMoney(data.total_price, theme.moneyFormat);
    
  });
</script>
Code language: HTML, XML (xml)

Awesome! Now that we have all of the codes that we need, we can finally reference all of them in our theme.liquid. So open your theme.liquid and add the following objects inside of the head tag of your theme.liquid:

{{ 'drawer.css' | asset_url | stylesheet_tag }}
{{ 'drawer.js' | asset_url | script_tag }}Code language: JavaScript (javascript)

Next, reference your drawer.liquid using the section tag inside of the body tag of your theme.liquid.

{% section 'drawer' %}Code language: JavaScript (javascript)

Awesome! Now, the last thing that we need to do is to customize our header.liquid to trigger the drawer.

Go to your sections folder and open the header.liquid. Once opened, look for the anchor tag ( <a></a> ) that uses either of the following href attribute values:

  • {{ routes.cart_url }}
  • /cart

For example, I have the following:

You can always find these elements using the search box ( CTRL + F ).

Once you have found it, replace the value of href attribute with a number sign symbol ( # ).

Then, we’ll apply the following attributes to this anchor tag.

data-drawer-trigger aria-controls="drawer-name" aria-expanded="false"Code language: HTML, XML (xml)

So, it should look like this now:

<a href="#" class="site-header__icon site-header__cart" data-drawer-trigger aria-controls="drawer-name" aria-expanded="false">
  {% include 'icon-cart' %}
  <span class="icon__fallback-text">{{ 'layout.cart.title' | t }}</span>
  <div id="CartCount" class="site-header__cart-count{% if cart.item_count == 0 %} hide{% endif %} critical-hidden" data-cart-count-bubble>
    <span data-cart-count>{{ cart.item_count }}</span>
    <span class="icon__fallback-text medium-up--hide">{{ 'layout.cart.items_count' | t: count: cart.item_count }}</span>
  </div>
</a>Code language: HTML, XML (xml)

Save the file. Now, that should allow you to display/hide the drawer whenever you click the Shopping bag button.

Conclusion

There you have it! That’s how simple it is to create a drawer for your Shopify stores. Now, for simplicity reasons, this is still not the best way to create a drawer for your Shopify stores. I don’t know if you noticed but the content of the cart will only show once you have either refreshed the page or opened another page. That’s not effective right? So how do you fixed that? Well, that’s when you’ll have to use events for your Shopify theme.

How To Customize Your Shopify Store with ScriptTag API

I’ve recently published a course where I teach how to create Shopify apps and in that course, I’ve taught how to add JavaScript files using ScriptTag API. However, I’ve never really used that lesson entirely to show how powerful ScriptTags are when it comes to improving Shopify stores.

In this article, we will talk about how you customize your Shopify store using ScriptTag API.

Getting Started

Before we start this tutorial, I want to disclose that I will be using the course Shopify app development with Node & React as the reference. What I mean is I will use the codes from the course BUT it does not truly matter as you will do the same steps for your ScriptTag file (aka JavaScript file).

Though, I recommend either taking my course or reading the documentary of Shopify to create a Shopify node project.

Okay, so let’s say we have the following JS file that allows us to install a ScriptTag to our development store.

const axios = require('axios');

const createScriptTag = async (accessToken, shop) => {
    const url = `https://${shop}/admin/api/2021-04/script_tags.json`;
    const src = 'https://test.com/test.js';

    let scriptTagExist = false;

    const shopifyHeader = (token) => ({
        'Content-Type': 'application/json',
        'X-Shopify-Access-Token': token,
    }); 

    const scriptTagBody = JSON.stringify({
        script_tag: {
            event: 'onload',
            src,
        },
    });

    const getScriptTags = await axios.get(url, { headers: shopifyHeader(accessToken) });

    getScriptTags.data.script_tags.map((script) => {
        if(script.src == src) {
            scriptTagExist = true;
        }
    });

    if(!scriptTagExist) {
        await axios.post(url, scriptTagBody, { headers: shopifyHeader(accessToken) })
            .then(response => { console.log(response); })
            .catch(error => console.log(error));
    } else {
        //IF THE SCRIPT TAG IS ALREADY INSTALLED, HERE IS WHERE YOU WILL BE DISPLAYING THE MESSAGE:
        //YOU HAVE ALREADY INSTALLED THE SCRIPTTAG
        return JSON.stringify({scriptTagStatus: true});
    }
}



module.exports = {
    createScriptTag
}
Code language: JavaScript (javascript)

In the code above, we have the function createScriptTag that uses the ScriptTag API endpoints (GET & POST) to check if there is an existing ScriptTag with the same URL that we set for the src variable. If there’s none then the function will create the Script Tag.

Once the script tag is installed, you can now work on the javascript file that you use for ScriptTag API.

Using Script Tags to customize store front

When I say script tags, these are the javascript files that you imported using the ScriptTag API and to be honest with you, it’s not that TOO complicated. In fact, once the javascript files are imported to your Shopify store, you can finally customize the JavaScript file and use it to add stuff or edit stuff to your Shopify storefront.

Say for example, we had the JavaScript file here https://test.com/test.js

And in that file, we have the following code:

alert("Example Alert");Code language: JavaScript (javascript)

By opening your Shopify store, you should have the following output:

JavaScript Alert

Woah, that’s it? That’s just too boring and simple…

Well, if you know JavaScript, you can basically DO ANYTHING you want to customize the frontend. Do you want to change the background color of your whole page? You can do that.

document.body.style.backgroundColor = "red";Code language: JavaScript (javascript)

Do you want to use a library and extend the functionality of your Shopify store? Heck yeah you can do that!

let darkmode;

function addWidget() {
  	darkmode = new Darkmode();
    darkmode.showWidget();
}

var script = document.createElement('script');
script.onload = function () {
    window.addEventListener('load', addWidget);
  
  	darkmode.toggle();
};

script.src = 'https://cdn.jsdelivr.net/npm/darkmode-js@1.5.7/lib/darkmode-js.min.js';

document.head.appendChild(script);

Code language: JavaScript (javascript)

Conclusion

There are a LOT of things that you can do with Script Tags. You know what they say? The sky is the limit! So go ahead and experiment with your codes and make your Shopify store more interactive and unique using JavaScript. There are hundreds of libraries out there that you can use to make your websites or store look like a badass. One of my favorites is the SweetAlert2. It’s lightweight and very easy to use.

I have a video using that library so if you’re interested, you can watch it here: