<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Fatih Samur</title>
    <description>The latest articles on Forem by Fatih Samur (@fatihsamur).</description>
    <link>https://forem.com/fatihsamur</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F493118%2F7303bc31-337f-4540-9432-4b7c11499d33.jpg</url>
      <title>Forem: Fatih Samur</title>
      <link>https://forem.com/fatihsamur</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/fatihsamur"/>
    <language>en</language>
    <item>
      <title>GraphQL Bulk Operation Example on Shopify API with PHP</title>
      <dc:creator>Fatih Samur</dc:creator>
      <pubDate>Wed, 02 Mar 2022 08:34:59 +0000</pubDate>
      <link>https://forem.com/fatihsamur/bulk-product-upload-on-shopify-using-graphql-admin-api-with-php-33ki</link>
      <guid>https://forem.com/fatihsamur/bulk-product-upload-on-shopify-using-graphql-admin-api-with-php-33ki</guid>
      <description>&lt;p&gt;In this post we will learn how to upload a list of products to our Shopify store by using their GraphQL API. It is a great tool for creating or updating multiple products on the same time if you have thousands of products on your store. Because with Shopify's REST API, you can only create one product per request and it might takes hours or even days to upload the products. So for the bigger stores that have thousands of products on their Shopify account, GraphQL API is a must to use tool. &lt;br&gt;
  But for the first time users of this API, it might be a little bit tricky to build the proper logic for uploading process. When I tried to do this for the first time, it took hours for me to understand the document of Shopify and then apply the logic to my code to upload my products. But here in this blog I will show you the code and explain every step of it. &lt;br&gt;
  First thing first, if you are here I suppose that you have a Shopify store :) and a bunch of product to upload on your store so I will not cover how to open a store on Shopify. Now as you have a Shopify store; open your admin dashboard page and go to &lt;strong&gt;Apps&lt;/strong&gt; section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2b4bh7ucje0hk0o4nqip.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2b4bh7ucje0hk0o4nqip.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the apps section, go to &lt;strong&gt;Develop apps&lt;/strong&gt; and click &lt;strong&gt;Create an app&lt;/strong&gt; button. &lt;br&gt;
After you create your app you will see your newly creaated app on your Apps list. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xqdx8g9jfkjzzmw2w9u.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xqdx8g9jfkjzzmw2w9u.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But to be able to use our newly created app we must first install it to our store and there are some configurations that we need to do for this. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiarvglm5s2s5mi6msow6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiarvglm5s2s5mi6msow6.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you see we need to get an access token and select our API access scope to install it. For this, go to &lt;strong&gt;Configure Admin API scopes&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb6m15lz0myxgi7f9v9p6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb6m15lz0myxgi7f9v9p6.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As our application will be working on the backend side of our store, we will give all the access to our app. So we will select all the options from top to bottom;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jkd73lvlordow9yhduf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jkd73lvlordow9yhduf.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After giving necessary access to our application, we can now install our app to Shopify store. If you have properly installed the app you will see your &lt;strong&gt;Admin API access token&lt;/strong&gt; on your app's API credentials like this;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1s1lwgfzckrcs4unkqg3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1s1lwgfzckrcs4unkqg3.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you reveal your access token, keep it in a safe place to be able to use it. Because Shopify shows this access token only once and after that you should copy and paste it in a secure file of your choice. Also keep your &lt;strong&gt;API key&lt;/strong&gt; and &lt;strong&gt;API secret key&lt;/strong&gt; too, as we will use them in our app. &lt;/p&gt;

&lt;p&gt;After these steps now we can jump into our real job :D &lt;br&gt;
Open up your favorite IDE and create a new PHP file to write our script. &lt;br&gt;
  We need to install the dependencies on our app before writing any code. (For this application, you need at least PHP 7.3 installed in your development environment. Also we use composer as our package manager.) Now type this on your terminal. &lt;/p&gt;

&lt;p&gt;Shopify PHP library installation:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

composer require shopify/shopify-api


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After installing Shoppify API library we can use it on our app like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

use Shopify\Clients\Graphql;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;But to be able to use the classes from our composer libraries we need to do the autoloading with this code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

require __DIR__ . '/vendor/autoload.php';


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After that, when we look at the documentation, it says every time you want to use your app, you should first set up your configurations. You can do that by calling the Shopify\Context::initialize method. Here is the example usage of the class that we can find in the documentation of Shopify.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

use Shopify\Context;
use Shopify\Auth\FileSessionStorage;

Context::initialize(
    $_ENV['SHOPIFY_API_KEY'],
    $_ENV['SHOPIFY_API_SECRET'],
    $_ENV['SHOPIFY_APP_SCOPES'],
    $_ENV['SHOPIFY_APP_HOST_NAME'],
    new FileSessionStorage('/tmp/php_sessions'),
    '2021-10',
    true,
    false,
);


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;(To not having an error on this stage you might need to manually create the tmp folder inside of your vendor/shopify/shopifyApi/src/Auth directory.)&lt;br&gt;
  As you see now we are using our API credentials at this point. Since we don't want to use our API credentials directly on our script we will create an &lt;strong&gt;.env&lt;/strong&gt; file on the main directory of our app. We will use a library called &lt;strong&gt;PHP dotenv&lt;/strong&gt; for the easier usage of our &lt;strong&gt;environment variables&lt;/strong&gt;. On your terminal, type this to install the library. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ composer require vlucas/phpdotenv


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Your &lt;strong&gt;.env&lt;/strong&gt; file should looks like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

SHOPIFY_ADMIN_API_ACCESS_TOKEN =  "YOUR ACCESS TOKEN HERE"
SHOPIFY_API_KEY = "YOUR API KEY HERE"
SHOPIFY_API_SECRET = "YOUR API SECRET HERE"
SHOPIFY_APP_HOST_NAME = "https://YOURSHOPNAME.myshopify.com/admin/api/2022-01/products.json"

SHOPIFY_APP_SCOPES = "read_analytics, write_assigned_fulfillment_orders, read_assigned_fulfillment_orders, write_customers, read_customers, write_discounts, read_discounts, write_draft_orders, read_draft_orders, write_files, read_files, write_fulfillments, read_fulfillments, read_gdpr_data_request, write_gift_cards, read_gift_cards, write_inventory, read_inventory, write_legal_policies, read_legal_policies, read_locations, write_marketing_events, read_marketing_events, write_merchant_managed_fulfillment_orders, read_merchant_managed_fulfillment_orders, read_online_store_navigation, write_online_store_pages, read_online_store_pages, write_order_edits, read_order_edits, write_orders, read_orders, write_payment_terms, read_payment_terms, write_price_rules, read_price_rules, write_product_listings, read_product_listings, write_products, read_products, write_reports, read_reports, write_resource_feedbacks, read_resource_feedbacks, write_script_tags, read_script_tags, write_shipping, read_shipping, write_locales, read_locales, read_shopify_payments_accounts, read_shopify_payments_bank_accounts, read_shopify_payments_disputes, read_shopify_payments_payouts, write_content, read_content, write_themes, read_themes, write_third_party_fulfillment_orders, read_third_party_fulfillment_orders, write_translations, read_translations"


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And by the help of dotenv library we can just type &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$_ENV['SHOPIFY_API_KEY']


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;if we need our API key.  &lt;/p&gt;

&lt;p&gt;By the way we took that &lt;strong&gt;SHOPIFY_APP_SCOPES&lt;/strong&gt; array from this page of our Shopify admin dashboard: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9wzt3eag4qwal0gsb15t.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9wzt3eag4qwal0gsb15t.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Until now our code should looks like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;?php

require __DIR__ . '/vendor/autoload.php';

use Shopify\Clients\Graphql;


use Shopify\Context;
use Shopify\Auth\FileSessionStorage;
use Shopify\Clients\Graphql;


$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv-&amp;gt;safeLoad();

Context::initialize(
  $_ENV['SHOPIFY_API_KEY'],
  $_ENV['SHOPIFY_API_SECRET'],
  $_ENV['SHOPIFY_APP_SCOPES'],
  $_ENV['SHOPIFY_APP_HOST_NAME'],
  new FileSessionStorage('&amp;lt;...&amp;gt;/vendor/shopify/shopify-api/src/Auth/tmp/shopify_api_sessions'),
  '2021-10',
  true,
  false,
);



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;One thing you should be careful about until now is: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

new FileSessionStorage('&amp;lt;...&amp;gt;/vendor/shopify/shopify-api/src/Auth/tmp/shopify_api_sessions'),


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;at this part you should enter the exact path of your &lt;strong&gt;tmp/sessions&lt;/strong&gt; file. &lt;/p&gt;

&lt;p&gt;After these first steps we will now start the bulk importing steps. This is the diagram that shows how the bulk importing works. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbkssh9c48o9hx4fvwh1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbkssh9c48o9hx4fvwh1.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So first of all we will create a JSONL file and add our GraphQL variables to it. In the JSONL file, each line represents one product input. The GraphQL Admin API runs once on each line of the input file. One input should take up one line only, no matter how complex the input object structure is. &lt;br&gt;
  Here is the example JSONL file structure that we use in this project.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

{"input":{"title":"Inventore excepturi ut.","productType":"provident","vendor":"Johns Group"}}
{"input":{"title":"Quod aspernatur.","productType":"corporis","vendor":"Vandervort-Rohan"}}
{"input":{"title":"Doloremque id.","productType":"ut","vendor":"Graham and Sons"}}
{"input":{"title":"Pariatur et velit.","productType":"dolores","vendor":"Koelpin, Hane and Steuber"}}
{"input":{"title":"Nisi laudantium.","productType":"voluptatem","vendor":"Keeling-Daniel"}}
{"input":{"title":"Exercitationem perferendis deleniti.","productType":"et","vendor":"Goldner, Nolan and Mertz"}}
{"input":{"title":"Cum architecto.","productType":"ipsa","vendor":"White Ltd"}}
{"input":{"title":"Mollitia at quo.","productType":"corporis","vendor":"Altenwerth Inc"}}
{"input":{"title":"Molestiae illum nihil.","productType":"dolorum","vendor":"Terry-Koch"}}
{"input":{"title":"Molestias dicta.","productType":"praesentium","vendor":"Swaniawski, Haley and Dooley"}}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You see we have 10 lines of input each representing one of the products. According to your product, input you can arrange your JSONL file. &lt;br&gt;
  Secondly, we need to upload our JSONL file to the Shopify. For that we need to first generate the upload URL and parameters.&lt;br&gt;
We will use the &lt;strong&gt;stagedUploadsCreate&lt;/strong&gt; mutation to generate the values that you need to authenticate the upload. The mutation returns an array of &lt;strong&gt;stagedMediaUploadTarget&lt;/strong&gt; instances. &lt;br&gt;
  Also this will be a POST query to Shopify API. To be able to make a query to Shopify API we need a new graphQL instance too. And we need our access token that we kept in &lt;strong&gt;.env&lt;/strong&gt; before. Here is the code for creating our instance:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$accessToken = $_ENV['SHOPIFY_ADMIN_API_ACCESS_TOKEN'];
$client = new Graphql("&amp;lt;YOUR-SHOP-NAME-HERE&amp;gt;.myshopify.com", $accessToken);


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And as I like to put my queries in a variable, my query would looks like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$staged_upload_query = '
mutation {
  stagedUploadsCreate(input:{
    resource: BULK_MUTATION_VARIABLES,
    filename: "bulk_op_vars",
    mimeType: "text/jsonl",
    httpMethod: POST
  }){
    userErrors{
      field,
      message
    },
    stagedTargets{
      url,
      resourceUrl,
      parameters {
        name,
        value
      }
    }
  }
}';


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This mutation will generate the values required to upload a JSONL file and be consumed by the bulkOperationRunMutation. So, I will take the response of that query and put it in a JSON file for see the results easily. Then we will use that variables in the next stage. Here is how I saved my response:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$response = $client-&amp;gt;query(['query' =&amp;gt; $staged_upload_que]);
$graphql_variables = $response-&amp;gt;getBody()-&amp;gt;getContents();
file_put_contents('graphql_variebles.json', $graphql_variables);



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The response should look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

{
  "data": {
    "stagedUploadsCreate": {
      "userErrors": [],
      "stagedTargets": [
        {
          "url": "https://shopify.s3.amazonaws.com",
          "resourceUrl": null,
          "parameters": [
            {
              "name": "key",
              "value": "tmp/61275799751/bulk/893d0275-8da9-4308-b0b8-133338f97812/products.jsonl"
            },
            { "name": "Content-Type", "value": "text/jsonl" },
            { "name": "success_action_status", "value": "201" },
            { "name": "acl", "value": "private" },
            {
              "name": "policy",
              "value": "eyJleHBpcmF0aW9uIjoiMjAyMi0wMi0yNFQwOToyMjo0NVoiLCJjb25kaXRpb25zIjpbeyJidWNrZXQiOiJzaG9waWZ5In0sWyJjb250ZW50LWxlbmd0aC1yYW5nZSIsMSwyMDk3MTUyMF0seyJrZXkiOiJ0bXAvNjEyNzU3OTk3NTEvYnVsay84OTNkMDI3NS04ZGE5LTQzMDgtYjBiOC0xMzMzMzhmOTc4MTIvcHJvZHVjdHMuanNvbmwifSx7IkNvbnRlbnQtVHlwZSI6InRleHQvanNvbmwifSx7InN1Y2Nlc3NfYWN0aW9uX3N0YXR1cyI6IjIwMSJ9LHsiYWNsIjoicHJpdmF0ZSJ9LHsieC1hbXotY3JlZGVudGlhbCI6IkFLSUFKWU01NTVLVllFV0dKREtRLzIwMjIwMjI0L3VzLWVhc3QtMS9zMy9hd3M0X3JlcXVlc3QifSx7IngtYW16LWFsZ29yaXRobSI6IkFXUzQtSE1BQy1TSEEyNTYifSx7IngtYW16LWRhdGUiOiIyMDIyMDIyNFQwODIyNDVaIn1dfQ=="
            },
            {
              "name": "x-amz-credential",
              "value": "AKIAJYM555KVYEWGJDKQ/20220224/us-east-1/s3/aws4_request"
            },
            { "name": "x-amz-algorithm", "value": "AWS4-HMAC-SHA256" },
            { "name": "x-amz-date", "value": "20220224T082245Z" },
            {
              "name": "x-amz-signature",
              "value": "b48e6dc6a00d867d418151672670bbfac6b178953c45b4775518b9951d1fc52d"
            }
          ]
        }
      ]
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 11,
      "actualQueryCost": 11,
      "throttleStatus": {
        "maximumAvailable": 1000.0,
        "currentlyAvailable": 989,
        "restoreRate": 50.0
      }
    }
  }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now after having these variables, we will send a POST request to API with them and at the and of our request we attach our &lt;strong&gt;JSONL&lt;/strong&gt; file that we prepared before. According to the documentation, the request should look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

curl --location --request POST 'https://shopify.s3.amazonaws.com' \
--form 'key="tmp/21759409/bulk/89e620e1-0252-43b0-8f3b-3b7075ba4a23/bulk_op_vars"' \
--form 'x-amz-credential="AKIAJYM555KVYEWGJDKQ/20210128/us-east-1/s3/aws4_request"' \
--form 'x-amz-algorithm="AWS4-HMAC-SHA256"' \
--form 'x-amz-date="20210128T190546Z"' \
--form 'x-amz-signature="5d063aac44a108f2e38b8294ca0e82858e6f44baf835eb81c17d37b9338b5153"' \
--form 'policy="eyJleHBpcmF0aW9uIjoiMjAyMS0wMS0yOFQyMDowNTo0NloiLCJjb25kaXRpb25zIjpbeyJidWNrZXQiOiJzaG9waWZ5In0sWyJjb250ZW50LWxlbmd0aC1yYW5nZSIsMSwyMDk3MTUyMF0seyJrZXkiOiJ0bXAvMjE3NTk0MDkvYnVsay84OWU2MjBlMS0wMjUyLTQzYjAtOGYzYi0zYjcwNzViYTRhMjMvYnVsa19vcF92YXJzIn0seyJDb250ZW50LVR5cGUiOiJ0ZXh0L2pzb25sIn0seyJzdWNjZXNzX2FjdGlvbl9zdGF0dXMiOiIyMDEifSx7ImFjbCI6InByaXZhdGUifSx7IngtYW16LWNyZWRlbnRpYWwiOiJBS0lBSllNNTU1S1ZZRVdHSkRLUS8yMDIxMDEyOC91cy1lYXN0LTEvczMvYXdzNF9yZXF1ZXN0In0seyJ4LWFtei1hbGdvcml0aG0iOiJBV1M0LUhNQUMtU0hBMjU2In0seyJ4LWFtei1kYXRlIjoiMjAyMTAxMjhUMTkwNTQ2WiJ9XX0="' \
--form 'acl="private"' \
--form 'Content-Type="text/jsonl"' \
--form 'success_action_status="201"' \
--form 'file=@"/Users/username/Documents/bulk_mutation_tests/products_long.jsonl"'


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;But as we are using PHP, I changed this CURL request to proper PHP code. So after converting it, here is my code for this POST request:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $curl_opt_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
$post = array(
  'key' =&amp;gt; $curl_key,
  'x-amz-credential' =&amp;gt; $curl_x_amz_credentials,
  'x-amz-algorithm' =&amp;gt; $curl_x_amz_algorithm,
  'x-amz-date' =&amp;gt; $curl_x_amz_date,
  'x-amz-signature' =&amp;gt; $curl_x_amz_signature,
  'policy' =&amp;gt; $curl_policy,
  'acl' =&amp;gt; 'private',
  'Content-Type' =&amp;gt; 'text/jsonl',
  'success_action_status' =&amp;gt; '201',
  'file' =&amp;gt; new \CURLFile('C:\Users\Fatih\Desktop\halukrugs\products.jsonl')
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

$result = curl_exec($ch);
if (curl_errno($ch)) {
  echo 'Error:' . curl_error($ch);
}
curl_close($ch);


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;At this part you will only change the exact path of your products.jsonl file. &lt;br&gt;
  And I will get the variables from the graphQLvariables.JSON file that we just created in the previous step. Here is how I get them: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$curl_opt_url = json_decode($graphql_variables)-&amp;gt;data-&amp;gt;stagedUploadsCreate-&amp;gt;stagedTargets[0]-&amp;gt;url;
$curl_key = json_decode($graphql_variables)-&amp;gt;data-&amp;gt;stagedUploadsCreate-&amp;gt;stagedTargets[0]-&amp;gt;parameters[0]-&amp;gt;value;
$curl_policy = json_decode($graphql_variables)-&amp;gt;data-&amp;gt;stagedUploadsCreate-&amp;gt;stagedTargets[0]-&amp;gt;parameters[4]-&amp;gt;value;
$curl_x_amz_credentials = json_decode($graphql_variables)-&amp;gt;data-&amp;gt;stagedUploadsCreate-&amp;gt;stagedTargets[0]-&amp;gt;parameters[5]-&amp;gt;value;
$curl_x_amz_algorithm = json_decode($graphql_variables)-&amp;gt;data-&amp;gt;stagedUploadsCreate-&amp;gt;stagedTargets[0]-&amp;gt;parameters[6]-&amp;gt;value;
$curl_x_amz_date = json_decode($graphql_variables)-&amp;gt;data-&amp;gt;stagedUploadsCreate-&amp;gt;stagedTargets[0]-&amp;gt;parameters[7]-&amp;gt;value;
$curl_x_amz_signature = json_decode($graphql_variables)-&amp;gt;data-&amp;gt;stagedUploadsCreate-&amp;gt;stagedTargets[0]-&amp;gt;parameters[8]-&amp;gt;value;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;But of course you should put these variables before your curl request. &lt;/p&gt;

&lt;p&gt;This request will return an &lt;strong&gt;xml&lt;/strong&gt; file and we need the &lt;strong&gt;KEY&lt;/strong&gt; of that result. I handled this by converting the result into an array and then take the &lt;strong&gt;KEY&lt;/strong&gt; as a string which I will use in the next step as &lt;strong&gt;stagedUploadPath&lt;/strong&gt; parameter. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$arr_result = simplexml_load_string(
  $result,
);


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now we can step into most critical part of our program. We will start creating our products in a bulk operation. We will use productCreate method inside of our bulkOperationRunMutation method. And we will pass it to the latter one as a string. And just as before I will put this query into a variable. Here is my query looks like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$product_create_query =
  'mutation {
    bulkOperationRunMutation(
    mutation: "mutation call($input: ProductInput!) { productCreate(input: $input) { product {title productType vendor} userErrors { message field } } }",
    stagedUploadPath: "' . (string)$arr_result-&amp;gt;Key . '") {
    bulkOperation {
      id
      url
      status
    }
    userErrors {
      message
      field
    }
  }
}';



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As you see this is actually two mutation but the productCreate is running inside the bulkOperationRunMutation process. Also be careful that we use the &lt;strong&gt;KEY&lt;/strong&gt; from the previous step as &lt;strong&gt;stagedUploadPath&lt;/strong&gt; parameter. &lt;/p&gt;

&lt;p&gt;And for the results of this query, you can use this code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$product_create_response = $client-&amp;gt;query(["query" =&amp;gt; $product_create_query]);



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now if this operation would work well, you should have a response like this: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

{
  "data": {
    "bulkOperationRunMutation": {
      "bulkOperation": {
        "id": "gid://shopify/BulkOperation/206005076024",
        "url": null,
        "status": "CREATED"
      },
      "userErrors": []
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 10,
      "actualQueryCost": 10
    }
  }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you see this result, that means you have successfully created your products in your Shopify store, Congratulations!!! :D :) You can check it in your products page of your Dashboard. &lt;/p&gt;

&lt;p&gt;But there is still some work that you might want to do. If you are using graphQL API, you must have thousands of products to upload Shopify. That means this process might still take some time to finish. And at this time you might want to check the status of your bulk operation whether it is completed or still running. Don't worry, it is an easy task. &lt;br&gt;
  To be able to check the status of our bulk operation, we need the id of that operation: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$bulk_op_id = json_decode($product_create_response-&amp;gt;getBody()-&amp;gt;getContents())-&amp;gt;data-&amp;gt;bulkOperationRunMutation-&amp;gt;bulkOperation-&amp;gt;id;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And we have another mutation for checking the operation status; &lt;strong&gt;currentBulkOperation&lt;/strong&gt;. &lt;br&gt;
  I use that query inside a function so that I can call it in a timer. Here is my function for checking the status of bulk op. :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

function check_bulk_op_status($client)
{
  $op_finish_que = 'query {
 currentBulkOperation(type: MUTATION) {
    id
    status
    errorCode
    createdAt
    completedAt
    objectCount
    fileSize
    url
    partialDataUrl
 }
}';

  $op_finish_resp = $client-&amp;gt;query(["query" =&amp;gt; $op_finish_que]);
  $str_op_finish_resp = $op_finish_resp-&amp;gt;getBody()-&amp;gt;getContents();
  $status_op_finish_resp = json_decode($str_op_finish_resp)-&amp;gt;data-&amp;gt;currentBulkOperation-&amp;gt;status;
  return $status_op_finish_resp;
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And by using that function, I check the status of my operation every 3 seconds (you can do longer in a real life scenario since it will take some time to finish the process and there is no need to check the status every3 seconds) with these line of codes:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$bulk_op_status = check_bulk_op_status($client);

while ($bulk_op_status != 'COMPLETED') {
  $bulk_op_status = check_bulk_op_status($client);
  var_dump('bulk operation status: ' . $bulk_op_status);
  sleep(3);
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This was the last step of bulk product uploading process. When you see "Completed" on your terminal, then your operation is done.&lt;/p&gt;

&lt;p&gt;Here is the complete code of this program:&lt;br&gt;
&lt;a href="https://github.com/fatihsamur/Bulk-Product-Upload-To-Shopify.git" rel="noopener noreferrer"&gt;Bulk PRoduct Upload&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And you can find the documentation on here: &lt;br&gt;
&lt;a href="https://shopify.dev/api/usage/bulk-operations/imports" rel="noopener noreferrer"&gt;Bulk import&lt;/a&gt;&lt;br&gt;
&lt;a href="https://shopify.dev/api/admin-graphql#top" rel="noopener noreferrer"&gt;GraphQL API&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/Shopify/shopify-php-api/tree/main/docs#readme" rel="noopener noreferrer"&gt;Shopify API&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lastly, I just cover the basics of product uploading for the first time users of Shopify Admin GraphQL API. I can't say I used all the best practices on my code but this was just a basic example of how we can use the GraphQL API of Shopify. Once you get the basics you can do more complex product upload tools by yourself. Hope this was a helpful article for those who are struggling to understand the Shopify's documentation. See you on the next articles.  &lt;/p&gt;

</description>
      <category>php</category>
      <category>graphql</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>An Introduction To Javascript </title>
      <dc:creator>Fatih Samur</dc:creator>
      <pubDate>Sat, 28 Nov 2020 00:45:51 +0000</pubDate>
      <link>https://forem.com/fatihsamur/what-is-javascript-2cfd</link>
      <guid>https://forem.com/fatihsamur/what-is-javascript-2cfd</guid>
      <description>&lt;p&gt;If you are learning programming most probably you have heard about Javascript a lot of time. As of 2020, Javascript is arguably the most popular programming language to ever exist. Let’s see what is so special about Javascript, what we can achieve with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Javascript and where is it used?
&lt;/h2&gt;

&lt;p&gt;Javascript is the language that make web pages alive. Along with HTML and CSS, it is one of the core component of web technologies. While HTML is responsible for structure of a web page and CSS is responsible for style, Javascript bring interactivity and behavior to web pages. &lt;/p&gt;

&lt;p&gt;By means of interactivity whenever you see a web page does more than sit there and show some static information, you can bet that Javascript is involved there. It allows you to dynamically update your content, control multimedia, change your style on the go and a lot more than that.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Briefly Javascript is a scripting language that allows you to implement complex features on web pages.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you don’t know what a scripting language is, basically it is also a programming language. The difference between the two is that scripting languages do not require the compilation step but rather interpreted. For example, a C program must needs to be compiled before running but a scripting language like Javascript or PHP need not be compiled. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why is it called Javascript?
&lt;/h2&gt;

&lt;p&gt;A lot of developer on their early stages of learning programming have the same confusion about the Javascript and Java. They are completely different programming languages. The reason why the names looks similar is a result of a marketing tactic when the Javascript first created in 1995. It was first named as LiveScript and then Netscape changed its name to Javascript because of the popularity of Java in that time. It also known as ECMAScript after its standardization in 1997. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why Javascript is so popular and widely used?
&lt;/h2&gt;

&lt;p&gt;It has been the most commonly used programming language in &lt;a href="https://insights.stackoverflow.com/survey/2020#technology-programming-scripting-and-markup-languages-professional-developers" rel="noopener noreferrer"&gt;Stackoverflow's Developer Survey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fue3ax0grnxvampwajuwi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fue3ax0grnxvampwajuwi.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are quite a few reasons why Javascript is so popular. Some of the reasons why JS is so popular are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  First of all it is an essential part of the web so learning Javascript is crucial for anyone who wants to become a web developer.&lt;/li&gt;
&lt;li&gt;  It is easy to learn Javascript. You don’t need any environment setup to write Js. Just open up your browsers Developer Tools, and start coding. It is as easy as this:
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;console.log("Hello world!")&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  It is a flexible language that can run almost everywhere. It is used for both front-end and back-end development. Also  you can build mobile apps with Javascript.
&lt;/li&gt;
&lt;li&gt;  It has a powerful  developer community behind and it is growing more and more.&lt;/li&gt;
&lt;li&gt;  It’s standardized and frequently updated with new versions.&lt;/li&gt;
&lt;li&gt;  It provide a great career opportunity. As more companies go digital, there is a great demand for people skilled in JavaScript.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Either you want to dive into programming or web development, Javascript is an excellent language to learn. Things you can do with Javascript are immense. &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>ecmascript</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
