Shopify Integration
Extend your Shopify Instance With A Custom Integration
A step-by-step tutorial
Do you need to extend the functionality in your existing Shopify store? Or perhaps you need further customization and complex features for your storefront?
Shopify exposes a REST API for 3rd party applications to integrate with in order to add functionality to Shopify stores. You can do this in several different ways:
- Reading and writing store data, either in response to user input or webhook event notifications
- Extending new features inside existing parts of the Shopify admin or POS
- Enhancing the way stores display information to customers
This guide will cover connecting to the Shopify Admin API 1 using Linx, providing a solid base to extend your Shopify instance with custom functionality.
About Linx
Linx is a development platform to build and host APIs, automation, and integrations. It is a general-purpose platform with no limitations on the technology to which it can connect and uses visual abstractions of programming concepts to make complex logic easy to build and maintain.
Lastly, as developers host their Shopify apps on their own infrastructure, Linx solutions include hosting for easier use.
Introduction
Creating a Linx application and connecting it to Shopify involves the following steps:
- Creating a private app and generating an API Key
- Configuring Linx to authenticate
- Customizing requests
Resources:
- Shopify REST API reference documentation 1: Developer documentation related to the Shopify Admin API.
- Template Linx application: ShopifyTemplate.lsoz (22.5 KB) (Download the Linx Designer to open and follow this guide.)
- Read more on Github
Create a private app
To access and modify your Shopify resources, you first need to register a private app with Shopify. This will then generate the relevant API Key which must be used when making requests from Linx.
To register a private app, log in to your Shopify dashboard, navigate to the Apps dashboard (Left menu > Apps). Click on the Manage private apps link which will open your private app dashboard. If you haven’t already, enable private app development.
Once enabled, click on the “Create New Private App” button. Give your app a name such as “LinxApp” and complete the contact details.
In the Admin API section, show the inactive permissions of the app (by default none are selected).
Select the relevant permissions, these will be the access scope of the linked application. In this guide we will be reading and writing data to the Customers and Products resources, you can modify the access permissions at a later stage.
Scroll to the bottom of the page and click Save then create app. Your app authentication details will be displayed:
- API Key: Key used as the
username
in the HTTP Basic authentication of the request as well as the request URL. - Password: Used as the
password
in the HTTP Basic authentication of the request. - Base URL: Example of the base URL to use when requesting to your instance.
Connect Linx to Shopify
To connect to the Shopify API, drag a CallRESTEndpointFNC onto a user-defined function and configure the relevant properties described below.
A best practice is creating $.Settings
values for all the needed constants in our application which may change at a later stage. By making these $.Settings
values, we can reference them throughout our Linx application and update them in a single place to have application-wide effects.
Create new $.Settings values like below and add your authentication details.
Creating the base URL
When making requests to the Shopify API, you need to build up the base URL of each request like below:
https://{apikey}:{password}@{hostname}/admin/api/{version}/{resource}.json
In Linx, this can be done via the use of expressions or using dynamic settings.
In the provided template application the URL is built up via a dynamic setting expression. The $.Settings.shopify_baseUrl
has the structure of the URL and placeholder references that reference other $.Settings
values. At runtime, the values referenced in the other settings will be concatenated into a base URL.
https://{shopify_apiKey}:{shopify_password}@{shopify_shopName}.myshopify.com/admin/api/{shopify_api_version}
At runtime, the value of $.Settings.shopify_baseUrl
will be:
When a request is made, the base URL can just be based on this $.Setting
value. The particular resource path can then be added in each request using an expression like below:
= $.Settings.shopify_baseURI + "/products" + ".json"
Authentication
Private applications authenticate with Shopify through basic HTTP authentication. This can be accomplished by completing the CallRESTEndpointFNC Authentication properties like below:
Querying and modifying data
The below examples are demonstrations of interacting with the Shopify API and Linx.
Querying customers
The below example deals with the Customer object. The function makes a GET
request to the /customers
the endpoint which returns a JSON string response containing a list of all the customers. The response is then imported by Linx into a custom-type object which is then used to structure the response body.
First, create a new Function and give it the name of GetCustomers
. Drag a CallRESTEndpointFNC onto the GetCustomers canvas.
Complete the Basic authentication details by referencing the API Key and password from earlier. Then configure the URL to be like the below (using the expression editor):
= $.Settings.shopify_baseURI + "/customers" + ".json"
Right-click on the CallRESTEndpointFNC and Add breakpoint and Enable logging, this will expose the runtime values of the objects in scope. Next, debug the GetCustomers function and take note of the response body returned in the Debug Values panel.
The response body is a JSON string like below:
{
"customers": [
{
"id": 207119551,
"email": "bob.norman@hostmail.com",
"accepts_marketing": false,
"created_at": "2021-01-01T14:46:48-05:00",
"updated_at": "2021-01-01T14:46:48-05:00",
"first_name": "Bob",
"last_name": "Norman",
"orders_count": 1,
"state": "disabled",
"total_spent": "199.65",
"last_order_id": 450789469,
"note": null,
"verified_email": true,
"multipass_identifier": null,
"tax_exempt": false,
"phone": "+16136120707",
"tags": "",
"last_order_name": "#1001",
"currency": "USD",
"addresses": [
{
"id": 207119551,
"customer_id": 207119551,
"first_name": null,
"last_name": null,
"company": null,
"address1": "Chestnut Street 92",
"address2": "",
"city": "Louisville",
"province": "Kentucky",
"country": "United States",
"zip": "40202",
"phone": "555-625-1199",
"name": "",
"province_code": "KY",
"country_code": "US",
"country_name": "United States",
"default": true
}
],
"accepts_marketing_updated_at": "2005-06-12T11:57:11-04:00",
"marketing_opt_in_level": null,
"tax_exemptions": [],
"admin_graphql_api_id": "gid://shopify/Customer/207119551",
"default_address": {
"id": 207119551,
"customer_id": 207119551,
"first_name": null,
"last_name": null,
"company": null,
"address1": "Chestnut Street 92",
"address2": "",
"city": "Louisville",
"province": "Kentucky",
"country": "United States",
"zip": "40202",
"phone": "555-625-1199",
"name": "",
"province_code": "KY",
"country_code": "US",
"country_name": "United States",
"default": true
}
}
]
}
This object contains a parent object containing a “customers” child object which contains a list of objects which contain the fields related to the product we are creating.
Next, we need to create a custom data type so Linx will know what to parse the response body into, this will allow us to work with individual field values in subsequent operations. Copy the value of CallRESTEndpoint.ResponseBody
from the Debug values panel or from the API documentation. Import the copied JSON string as a new Type. This will create a data object or type for you to structure the response data into. Configure the CallRESTEndpointFNC to have an Output type of the newly imported user-defined type.
More in working with responses here. You can then return the details as an output of the custom function.
Adding products
In the below example, a Product will be added to Shopify. This will involve making a POST
request to the /products
endpoint. A JSON structure containing details of a Product
will be submitted as the request body.
Example request:
POST /admin/api/2021-01/products.json
{
"product": {
"title": "Burton Custom Freestyle 151",
"body_html": "<strong>Good snowboard!</strong>",
"vendor": "Burton",
"product_type": "Snowboard",
"tags": [
"Barnes & Noble",
"John's Fav",
"Big Air"
]
}
}
In the below example we are going to create a user-defined function that will take in the details of a product as the input parameters. These details will then be assigned to the user-defined type and submitted in a request.
First, In order to submit a valid JSON data structured like the above, you need to create a user-defined Type that matches the fields in the product
object, either manually or by importing the provided JSON
example as a new Type with the name of “newProduct”. This will create two types, a parent newProduct
which holds a child newProduct_product
.
This user-defined type is then available to reference across your Linx application to structure data.
Next, we are going to create a user-defined function that will take in data in this format and then submit this data to the Shopify API.
To do this, create a new user-defined function with the name of “CreateProduct”, with an input parameter with the name of product
and the Type of product
. When this CreateProduct user-defined function is called from somewhere else in the application, the structure of the child object will be able to be used to pass data through. The parent product is not needed as an input parameter as it just creates another level, we can assign it later inside the function.
For the request body, we are going to submit a newProduct
type from earlier in JSON format. Currently, the CreateProduct function takes in an input parameter of the type newProduct_product
. However, for the request to succeed, we need to submit the entire structure of newProduct
. To do this, we need to assign the input parameter productDetails
details as the child newProduct_product
of newProduct
. To do this, drag an instance of the newProduct
type from the Solution Explorer onto the CreateProduct canvas. Expand its field values properties and in the product
field, reference the input parameter productDetails
.
Now to make the request using the newProduct
type. Inside the CreateProduct function, drag a CallRESTEndpointFNC onto the canvas. Configure the authentication credentials and the request URL.
Now we need to submit the local instance newProduct
as the request body. Change the Method of the request to POST
and set the Body format as JSON
. For the Body property, reference the local newProduct
.
Now we can make a request to test it out.
Debug ➤ the CreateProduct function and add debug input parameter values for the new product. Add some breakpoints and logging to see how the input data is assigned to a local instance of the newProduct
type and then submitted as a JSON
body with a successful 201 - Created
the response being returned.
A new product should be visible on the Shopify products dashboard:
You can then import the response as a new user-defined type and set it as the Output type of the CallRESTEndpointFNC . When a new product is now created, the newly added details and some metadata including the new id
are then available in subsequent functions such as logging them to a database with an ExecuteSQLFNC or writing to a file using a TextFileWriteFNC .
That’s it! You’re done!
Don’t forget to follow The Lean Programmer Publication for more such articles, and subscribe to our newsletter tinyletter.com/TheLeanProgrammer