Development discussions around Shopify APIs
Hi Everyone,
Hope all are doing well.
I want to update the theme files(ex. product-template.liquid) when my app is installed in store.
Please help me out to update liquid files using API.
Did you check the documentation? You can do so with the assets endpoint.
Alex | Shopify
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution
- To learn more visit the Shopify Help Center or the Shopify Blog
Thanks for your reply.
I used the following assets API to first get the current .liquid contents:
GET /admin/themes/#{theme_id}/assets.json?asset[key]=templates/index.liquid&theme_id=828155753
Then I added my extra code to the fetched contents and I used the following api to update the existing theme file
PUT /admin/themes/#{theme_id}/assets.json
{ "asset": { "key": "templates/index.liquid", "value": "<img src='backsoon-postit.png'><p>We are busy updating the store for you and will be back within the hour.</p>" } }
But It returns error regarding invalid data and theme file do not get updated.
Is there any specfic method using which I can convert the contents that are updated, so that API will accept my new updated contents?
Can you please help me out to accomplish this.
Sorry for digging up a dead thread, but incase you were lost on this, the value you had in the asset PUT had an open
<img src='test.png'>
tag without it closing
<img src='test.png' alt='image' />
which is probably why your data is coming back as invalid and not updating. Let me know if this helps. Also notice you'll want to add an alt attribute as best practice.
You're going to have to provide more details on what's happening from your perspective. Do you have a specific response and/or `X-Request-Id` response header I can look at?
Alex | Shopify
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution
- To learn more visit the Shopify Help Center or the Shopify Blog
Hi Alex Richter,
Below is the response I get when I try to update theme file.
Hope this will help to understand what is the issue.
Response: ShopifyApiException Object ( [method:protected] => PUT [path:protected] => /admin/themes/182107796/assets.json [params:protected] => Array ( [asset] => Array ( [key] => sections\/product-template.liquid [value] =>
{% comment %} Get first variant, or deep linked one {% endcomment %} {%- assign current_variant = product.selected_or_first_available_variant -%} {%- assign product_image_zoom_size = '1024x1024' -%} {%- assign product_image_scale = '2' -%} {%- assign enable_zoom = section.settings.enable_zoom -%} {% case section.settings.image_size %} {% when 'small' %} {%- assign product_image_width = 'medium-up--one-third' -%} {%- assign product_description_width = 'medium-up--two-thirds' -%} {%- assign product_thumbnail_width = 'medium-up--one-third' -%} {%- assign height = 345 -%} {% when 'medium' %} {%- assign product_image_width = 'medium-up--one-half' -%} {%- assign product_description_width = 'medium-up--one-half' -%} {%- assign product_thumbnail_width = 'medium-up--one-quarter' -%} {%- assign height = 530 -%} {% when 'large' %} {%- assign product_image_width = 'medium-up--two-thirds' -%} {%- assign product_description_width = 'medium-up--one-third' -%} {%- assign product_thumbnail_width = 'medium-up--one-fifth' -%} {%- assign height = 720 -%} {% when 'full' %} {%- assign product_image_width = '' -%} {%- assign product_description_width = '' -%} {%- assign product_thumbnail_width = 'medium-up--one-eighth' -%} {%- assign height = 1090 -%} {%- assign enable_zoom = false -%} {% endcase %}{%- assign featured_image = product.selected_or_first_available_variant.featured_image | default: product.featured_image -%} {% for image in product.images %} {% capture img_id %}FeaturedImage-{{ section.id }}-{{ image.id }}{% endcapture %} {% capture img_class %}product-featured-img{% endcapture %} {% capture zoom_img_id %}FeaturedImageZoom-{{ section.id }}-{{ image.id }}{% endcapture %} {% capture img_wrapper_id %}{{ zoom_img_id }}-wrapper{% endcapture %} {%- assign img_url = image | img_url: '1x1' | replace: '_1x1.', '_{width}x.' -%} {% include 'image-style' with small_style: true, width: height, height: height, wrapper_id: img_wrapper_id, img_id: img_id %}
{% endfor %} {% if product.images.size > 1 %} {% if product.images.size > 3 %} {%- assign enable_thumbnail_slides = true -%} {% endif %}
{% if enable_thumbnail_slides == true %}
{% endif %}
{% if enable_thumbnail_slides == true %}
{% endif %}
{% endif %}
{{ product.title }}
{% if section.settings.show_vendor %}
{{ product.vendor }}
{% endif %}
{% if current_variant.compare_at_price > current_variant.price %} {{ 'products.product.regular_price' | t }} {{ current_variant.compare_at_price | money }} {{ current_variant.price | money }} {{ 'products.product.on_sale' | t }} {% else %} {{ 'products.product.regular_price' | t }} {{ current_variant.compare_at_price | money }} {{ current_variant.price | money }} {{ 'products.product.on_sale' | t }} {% endif %}
{% unless product.options.size == 1 and product.variants[0].title == 'Default Title' %} {% for option in product.options_with_values %}
{{ option.name }}
{% endfor %} {% endunless %}
{% if section.settings.show_quantity_selector %}
{{ 'products.product.quantity' | t }}
{% endif %}
{{ product.description }}
{% if section.settings.show_share_buttons %} {% include 'social-sharing', share_title: product.title, share_permalink: product.url, share_image: product %} {% endif %}
{% if collection %}
{% endif %} {% unless product == empty %} {% endunless %} {% schema %} { "name": "Product pages", "settings": [ { "type": "select", "id": "image_size", "label": "Image size", "options": [ { "value": "small", "label": "Small" }, { "value": "medium", "label": "Medium" }, { "value": "large", "label": "Large" }, { "value": "full", "label": "Full-width" } ], "default": "medium" }, { "type": "checkbox", "id": "show_quantity_selector", "label": "Show quantity selector", "default": false }, { "type": "checkbox", "id": "show_variant_labels", "label": "Show variant labels", "default": true }, { "type": "checkbox", "id": "show_vendor", "label": "Show vendor", "default": false }, { "type": "checkbox", "id": "enable_zoom", "label": "Enable image zoom", "default": true }, { "type": "checkbox", "id": "show_share_buttons", "label": "Show social sharing buttons", "default": true } ] } {% endschema %} ) ) [response_headers:protected] => Array ( [http_status_code] => 400 [http_status_message] => Bad Request [server] => nginx [date] => Thu, 12 Apr 2018 06:55:21 GMT [content-type] => application/json [transfer-encoding] => chunked [connection] => keep-alive [x-sorting-hat-podid] => 79 [x-sorting-hat-podid-cached] => 1 [x-sorting-hat-shopid] => 22383817 [x-sorting-hat-section] => pod [x-sorting-hat-shopid-cached] => 1 [x-content-type-options] => nosniff [x-download-options] => noopen [x-permitted-cross-domain-policies] => none [x-xss-protection] => 1; mode=block [x-dc] => chi2,gcp-us-central1 [via] => 1.1 google [alt-svc] => clear [x-request-id] => b0cee1d1-a355-4d33-bb90-409d2e959776 ) [response:protected] => Array ( [error] => 822: unexpected token at '{"asset":{"key":"sections\/product-template.liquid","value":"
n n n nn {% comment %}n Get first variant, or deep linked onen {% endcomment %}n {%- assign current_variant = product.selected_or_first_available_variant -%}n {%- assign product_image_zoom_size = '1024x1024' -%}n {%- assign product_image_scale = '2' -%}n {%- assign enable_zoom = section.settings.enable_zoom -%}nn {% case section.settings.image_size %}n {% when 'small' %}n {%- assign product_image_width = 'medium-up--one-third' -%}n {%- assign product_description_width = 'medium-up--two-thirds' -%}n {%- assign product_thumbnail_width = 'medium-up--one-third' -%}n {%- assign height = 345 -%}n {% when 'medium' %}n {%- assign product_image_width = 'medium-up--one-half' -%}n {%- assign product_description_width = 'medium-up--one-half' -%}n {%- assign product_thumbnail_width = 'medium-up--one-quarter' -%}n {%- assign height = 530 -%}n {% when 'large' %}n {%- assign product_image_width = 'medium-up--two-thirds' -%}n {%- assign product_description_width = 'medium-up--one-third' -%}n {%- assign product_thumbnail_width = 'medium-up--one-fifth' -%}n {%- assign height = 720 -%}n {% when 'full' %}n {%- assign product_image_width = '' -%}n {%- assign product_description_width = '' -%}n {%- assign product_thumbnail_width = 'medium-up--one-eighth' -%}n {%- assign height = 1090 -%}n {%- assign enable_zoom = false -%}n {% endcase %}nnnn {%- assign featured_image = product.selected_or_first_available_variant.featured_image | default: product.featured_image -%}n {% for image in product.images %}n {% capture img_id %}FeaturedImage-{{ section.id }}-{{ image.id }}{% endcapture %}n {% capture img_class %}product-featured-img{% endcapture %}n {% capture zoom_img_id %}FeaturedImageZoom-{{ section.id }}-{{ image.id }}{% endcapture %}n {% capture img_wrapper_id %}{{ zoom_img_id }}-wrapper{% endcapture %}n {%- assign img_url = image | img_url: '1x1' | replace: '_1x1.', '_{width}x.' -%}nn {% include 'image-style' with small_style: true, width: height, height: height, wrapper_id: img_wrapper_id, img_id: img_id %}nnn
n n
nn {% endfor %}nn nn {% if product.images.size > 1 %}n {% if product.images.size > 3 %}n {%- assign enable_thumbnail_slides = true -%}n {% endif %}nn
n {% if enable_thumbnail_slides == true %}n
n {% endif %}n
n {% if enable_thumbnail_slides == true %}n
n {% endif %}n
n {% endif %}n
nn
nnn
{{ product.title }}
nn {% if section.settings.show_vendor %}n
{{ product.vendor }}
n {% endif %}nnn nn nn
n {% if current_variant.compare_at_price > current_variant.price %}n {{ 'products.product.regular_price' | t }}n {{ current_variant.compare_at_price | money }}n n n {{ current_variant.price | money }}n n {{ 'products.product.on_sale' | t }}n n {% else %}n {{ 'products.product.regular_price' | t }}n {{ current_variant.compare_at_price | money }}n n n {{ current_variant.price | money }}n n {{ 'products.product.on_sale' | t }}n n {% endif %}n
nn
n {% unless product.options.size == 1 and product.variants[0].title == 'Default Title' %}n {% for option in product.options_with_values %}n
n n {{ option.name }}n n
n
n {% endfor %}n {% endunless %}nn
nn {% if section.settings.show_quantity_selector %}n
n {{ 'products.product.quantity' | t }}n n
n {% endif %}nn
n
n
n
nnnn
n {{ product.description }}n
nn {% if section.settings.show_share_buttons %}n {% include 'social-sharing', share_title: product.title, share_permalink: product.url, share_image: product %}n {% endif %}nnnnn
nn{% if collection %}n
n{% endif %}nn{% unless product == empty %}n n{% endunless %}nnn{% schema %}n {n "name": "Product pages",n "settings": [n {n "type": "select",n "id": "image_size",n "label": "Image size",n "options": [n {n "value": "small",n "label": "Small"n },n {n "value": "medium",n "label": "Medium"n },n {n "value": "large",n "label": "Large"n },n {n "value": "full",n "label": "Full-width"n }n ],n "default": "medium"n },n {n "type": "checkbox",n "id": "show_quantity_selector",n "label": "Show quantity selector",n "default": falsen },n {n "type": "checkbox",n "id": "show_variant_labels",n "label": "Show variant labels",n "default": truen },n {n "type": "checkbox",n "id": "show_vendor",n "label": "Show vendor",n "default": falsen },n {n "type": "checkbox",n "id": "enable_zoom",n "label": "Enable image zoom",n "default": truen },n {n "type": "checkbox",n "id": "show_share_buttons",n "label": "Show social sharing buttons",n "default": truen }n ]n }n{% endschema %}n"}}' ) [message:protected] => Bad Request [string:Exception:private] => [code:protected] => 400 [file:protected] => /Applications/XAMPP/xamppfiles/htdocs/DemoApp/application/libraries/Shopifyapi.php [line:protected] => 77 [trace:Exception:private] => Array ( [0] => Array ( [file] => /Applications/XAMPP/xamppfiles/htdocs/DemoApp/application/controllers/Homepage.php [line] => 560 [function] => call [class] => Shopifyapi [type] => -> [args] => Array ( [0] => PUT [1] => /admin/themes/182107796/assets.json [2] => Array ( [asset] => Array ( [key] => sections\/product-template.liquid [value] =>
{% comment %} Get first variant, or deep linked one {% endcomment %} {%- assign current_variant = product.selected_or_first_available_variant -%} {%- assign product_image_zoom_size = '1024x1024' -%} {%- assign product_image_scale = '2' -%} {%- assign enable_zoom = section.settings.enable_zoom -%} {% case section.settings.image_size %} {% when 'small' %} {%- assign product_image_width = 'medium-up--one-third' -%} {%- assign product_description_width = 'medium-up--two-thirds' -%} {%- assign product_thumbnail_width = 'medium-up--one-third' -%} {%- assign height = 345 -%} {% when 'medium' %} {%- assign product_image_width = 'medium-up--one-half' -%} {%- assign product_description_width = 'medium-up--one-half' -%} {%- assign product_thumbnail_width = 'medium-up--one-quarter' -%} {%- assign height = 530 -%} {% when 'large' %} {%- assign product_image_width = 'medium-up--two-thirds' -%} {%- assign product_description_width = 'medium-up--one-third' -%} {%- assign product_thumbnail_width = 'medium-up--one-fifth' -%} {%- assign height = 720 -%} {% when 'full' %} {%- assign product_image_width = '' -%} {%- assign product_description_width = '' -%} {%- assign product_thumbnail_width = 'medium-up--one-eighth' -%} {%- assign height = 1090 -%} {%- assign enable_zoom = false -%} {% endcase %}{%- assign featured_image = product.selected_or_first_available_variant.featured_image | default: product.featured_image -%} {% for image in product.images %} {% capture img_id %}FeaturedImage-{{ section.id }}-{{ image.id }}{% endcapture %} {% capture img_class %}product-featured-img{% endcapture %} {% capture zoom_img_id %}FeaturedImageZoom-{{ section.id }}-{{ image.id }}{% endcapture %} {% capture img_wrapper_id %}{{ zoom_img_id }}-wrapper{% endcapture %} {%- assign img_url = image | img_url: '1x1' | replace: '_1x1.', '_{width}x.' -%} {% include 'image-style' with small_style: true, width: height, height: height, wrapper_id: img_wrapper_id, img_id: img_id %}
{% endfor %} {% if product.images.size > 1 %} {% if product.images.size > 3 %} {%- assign enable_thumbnail_slides = true -%} {% endif %}
{% if enable_thumbnail_slides == true %}
{% endif %}
{% if enable_thumbnail_slides == true %}
{% endif %}
{% endif %}
{{ product.title }}
{% if section.settings.show_vendor %}
{{ product.vendor }}
{% endif %}
{% if current_variant.compare_at_price > current_variant.price %} {{ 'products.product.regular_price' | t }} {{ current_variant.compare_at_price | money }} {{ current_variant.price | money }} {{ 'products.product.on_sale' | t }} {% else %} {{ 'products.product.regular_price' | t }} {{ current_variant.compare_at_price | money }} {{ current_variant.price | money }} {{ 'products.product.on_sale' | t }} {% endif %}
{% unless product.options.size == 1 and product.variants[0].title == 'Default Title' %} {% for option in product.options_with_values %}
{{ option.name }}
{% endfor %} {% endunless %}
{% if section.settings.show_quantity_selector %}
{{ 'products.product.quantity' | t }}
{% endif %}
{{ product.description }}
{% if section.settings.show_share_buttons %} {% include 'social-sharing', share_title: product.title, share_permalink: product.url, share_image: product %} {% endif %}
{% if collection %}
{% endif %} {% unless product == empty %} {% endunless %} {% schema %} { "name": "Product pages", "settings": [ { "type": "select", "id": "image_size", "label": "Image size", "options": [ { "value": "small", "label": "Small" }, { "value": "medium", "label": "Medium" }, { "value": "large", "label": "Large" }, { "value": "full", "label": "Full-width" } ], "default": "medium" }, { "type": "checkbox", "id": "show_quantity_selector", "label": "Show quantity selector", "default": false }, { "type": "checkbox", "id": "show_variant_labels", "label": "Show variant labels", "default": true }, { "type": "checkbox", "id": "show_vendor", "label": "Show vendor", "default": false }, { "type": "checkbox", "id": "enable_zoom", "label": "Enable image zoom", "default": true }, { "type": "checkbox", "id": "show_share_buttons", "label": "Show social sharing buttons", "default": true } ] } {% endschema %} ) ) ) ) [1] => Array ( [file] => /Applications/XAMPP/xamppfiles/htdocs/DemoApp/system/core/CodeIgniter.php [line] => 514 [function] => themeupdate [class] => Homepage [type] => -> [args] => Array ( ) ) [2] => Array ( [file] => /Applications/XAMPP/xamppfiles/htdocs/DemoApp/index.php [line] => 295 [args] => Array ( [0] => /Applications/XAMPP/xamppfiles/htdocs/DemoApp/system/core/CodeIgniter.php ) [function] => require_once ) ) [previous:Exception:private] => )
I think the following error response sorted from above response may be helpful:
[response_headers:protected] => Array ( [http_status_code] => 400 [http_status_message] => Bad Request [server] => nginx [date] => Thu, 12 Apr 2018 06:55:21 GMT [content-type] => application/json [transfer-encoding] => chunked [connection] => keep-alive [x-sorting-hat-podid] => 79 [x-sorting-hat-podid-cached] => 1 [x-sorting-hat-shopid] => 22383817 [x-sorting-hat-section] => pod [x-sorting-hat-shopid-cached] => 1 [x-content-type-options] => nosniff [x-download-options] => noopen [x-permitted-cross-domain-policies] => none [x-xss-protection] => 1; mode=block [x-dc] => chi2,gcp-us-central1 [via] => 1.1 google [alt-svc] => clear [x-request-id] => b0cee1d1-a355-4d33-bb90-409d2e959776 ) [response:protected] => Array ( [error] => 822: unexpected token at '{"asset":{"key":"sections\/product-template.liquid","value":"
n n n nn {% comment %}n Get first variant, or deep linked onen {% endcomment %}n {%- assign current_variant = product.selected_or_first_available_variant -%}n {%- assign product_image_zoom_size = '1024x1024' -%}n {%- assign product_image_scale = '2' -%}n {%- assign enable_zoom = section.settings.enable_zoom -%}nn {% case section.settings.image_size %}n {% when 'small' %}..........
It looks to me like your json might not be formatted correctly. I would suggest running everything past "822: unexpected token at" through a JSON linter.
Alex | Shopify
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution
- To learn more visit the Shopify Help Center or the Shopify Blog
Hi Alex Richter,
Thank you for your help but I am still not able to update the theme files using API.
Can you please create one demo code that works and I will implement in my app.
I am requesting you for this. Please help me out am stuck into this for so many days.
Please help me.
Thanks and regards
Hi Alex Richter,
Waiting for your reply. Still I have got nothing and stucked at same thing.
Any help will be appreciated.
I'm not going to be able to give you a code example in your language of choice, but maybe showing you how to do it in my preferred language will help. I'll update a theme file using Ruby with the HTTParty library.
require "httparty"
uri = URI("https://shop.myshopify.com/admin/assets.json")
options = {
headers: { "X-Shopify-Access-Token" => "9db6c3dba7b61676357aedf7nnb6b0c9" },
body: {
asset: {
key: "templates/product.liquid",
value: "<h1>Foobar</h1>"
}
}
}
response = HTTParty.put(uri, options)
puts response
If you're still experiencing the same issue it's because your JSON is invalid (syntactically). I would recommend looking elsewhere for how to properly assembly a JSON body if that's what the issue still is. The above is how this is accomplished in Ruby without issue.
Cheers.
Alex | Shopify
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution
- To learn more visit the Shopify Help Center or the Shopify Blog
Thanks for your reply.
Can you show me how would you inject html code(for ex. <div class="my-class"></div>) at the end of product-template.liquid file?
The example you shown is one of the simplest example and I think everybody will able to add only
<h1>Foobar</h1>
into the file. i have already tried to add simple html data into the file and I am able to do it.
What I want to do is, I want to add "<div class="my-class"></div>" this html data at the end of "product-template.liquid" file with all old data exist in "product-template.liquid" file.
I hope you understood my requirement and will tell me what I should do.
Hey Milind,
You would just retrieve the whole body of the file, store it in a string, and append the element you want to add to the end before saving.
require "httparty"
response = HTTParty.get(URI("https://shop.myshopify.com/admin/themes/163335430/assets.json?asset[key]=templates/product.liquid&th..."),
{
headers: {
"X-Shopify-Access-Token" => "f8ef0cc63c5af906cd46a8d24k3l24d123"
}
})
product_liquid_body = JSON.parse(response.body)["asset"]["value"]
product_liquid_body = "#{product_liquid_body}<div class=\"my-class\"></div>\n"
put_response = HTTParty.put(URI("https://shop.myshopify.com/admin/themes/163335430/assets.json"),
{
headers: {
"X-Shopify-Access-Token" => "f8ef0cc63c5af906cd46a8d24k3l24d123"
},
body: {
"asset" => {
"key" => "templates/product.liquid",
"value" => product_liquid_body
}
}
})
Alex | Shopify
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution
- To learn more visit the Shopify Help Center or the Shopify Blog
Hello Alex,
Your answer found me as very useful. Thanks for that.
I am looking for some solution in which I can place my code in between the existing template code.
For example, I want to modify the product template to show "call for price" button instead of Add to cart button when price of the product is zero.
Can you please help me with that?
THank you for the code.
It helped me with current theme
User | RANK |
---|---|
10 | |
4 | |
3 | |
3 | |
3 |
We're excited to announce improvements to the threaded messaging experience in our communi...
By TyW May 31, 2023Thank you to everyone who participated in our AMA with Klaviyo. It was great to see so man...
By Jacqui May 30, 2023Photo by Marco Verch Sales channels on Shopify are various platforms where you can sell...
By Ollie May 25, 2023