How to update theme files using API

Milind2
Excursionist
25 0 11

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.

Replies 13 (13)
Alex
Shopify Staff
Shopify Staff
1561 81 339

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

Milind2
Excursionist
25 0 11

Hi Alex Richter,

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.

barley
Shopify Partner
1 0 0

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.

Alex
Shopify Staff
Shopify Staff
1561 81 339

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

Milind2
Excursionist
25 0 11

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 %}

{{ image.alt | escape }}

{% endfor %} {% if product.images.size > 1 %} {% if product.images.size > 3 %} {%- assign enable_thumbnail_slides = true -%} {% endif %}

{% if enable_thumbnail_slides == true %}

          {% endif %}
          
  • {% for image in product.images %}
  • {{ image.alt | escape }}
  • {% endfor %}

{% 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 %}

{% include 'icon-arrow-left' %} {{ 'products.product.back_to_collection' | t: title: collection.titl...

{% 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 {{ image.alt | escape }}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 {% for image in product.images %}n
  • n n {{ image.alt | escape }}n n
  • n {% endfor %}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 n {% include 'icon-arrow-left' %}n {{ 'products.product.back_to_collection' | t: title: collection.t...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 %}

{{ image.alt | escape }}

{% endfor %} {% if product.images.size > 1 %} {% if product.images.size > 3 %} {%- assign enable_thumbnail_slides = true -%} {% endif %}

{% if enable_thumbnail_slides == true %}

          {% endif %}
          
  • {% for image in product.images %}
  • {{ image.alt | escape }}
  • {% endfor %}

{% 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 %}

{% include 'icon-arrow-left' %} {{ 'products.product.back_to_collection' | t: title: collection.titl...

{% 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' %}..........

Alex
Shopify Staff
Shopify Staff
1561 81 339

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

Milind2
Excursionist
25 0 11

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

 

Milind2
Excursionist
25 0 11

Hi Alex Richter,

Waiting for your reply. Still I have got nothing and stucked at same thing.

Any help will be appreciated.

 
Alex
Shopify Staff
Shopify Staff
1561 81 339

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

Milind2
Excursionist
25 0 11

Hi Alex Richter,

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.

Alex
Shopify Staff
Shopify Staff
1561 81 339

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

rahulevince
Shopify Partner
3 0 0

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?

 

upserve
Shopify Partner
28 0 0

THank you for the code.

It helped me with current theme

If helpful then please Like and Accept Solution.
Want to modify or custom changes on store Hire me.
- Feel free to contact me on https://ua.linkedin.com/in/yanchuga regarding any help
Shopify Partner | Telegram : https://t.me/yanwinner