Shopify / buy-button-js

BuyButton.js is a highly customizable UI library for adding ecommerce functionality to any website.
http://shopify.github.io/buy-button-js/
MIT License
242 stars 114 forks source link

Adding line items with custom attributes / line item properties #598

Open napter opened 5 years ago

napter commented 5 years ago

The JS buy SDK has a way to add custom attributes. I cannot find an equivalent way to add those to line items in the cart when using the JS buy button. I have tried to add them items to the cart manually following the instructions linked above - but cannot find any documentation on how to get the checkout ID. "client.checkout.id" is unassigned.

`

    ui.createComponent('product', {
        id: 2461692624960,
        node: document.getElementById('shopifynode'),
        options: {
            product: {
            buttonDestination: 'cart',
            },
            cart: {
                startOpen: true,
                'events': {
                }
            }
        }
    }).then((c) => {

    const lineItem = {variantId: 'Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0VmFyaWFudC8yMjkyOTcwMjU4NDM4NA==', quantity: 1};
    client.checkout.addLineItems(client.checkout.id, [lineItem]).then((updatedCheckout) => {
      //checkoutWindow.location = updatedCheckout.webUrl;
      console.log(checkout.lineItems);
    });
    }

`

napter commented 5 years ago

I have looked through the code and It does not appear that there is any way to add custom attributes using the buy button SDK. Can this be added? I have found a way to update the cart using ui.components.cart[0]..props.client.checkout.addLineItems(cart.model.id, [lineItem]) but then the cart doesn't refresh.

rebeccajfriedman commented 5 years ago

We are tracking this issue in our backlog. We will follow up here when we have an update.

hyunilmmt commented 5 years ago

This would be a great feature to add to the Buy Button.

Dave84c commented 5 years ago

In the meantime, if it's urgent, you can grab it here. Made a fork with custom attributes working. See index files for examples: https://github.com/Dave84c/buy-button-js

reigelgallarde commented 4 years ago

any update on this?

mizujin commented 4 years ago

In the meantime, if it's urgent, you can grab it here. Made a fork with custom attributes working. See index files for examples: https://github.com/Dave84c/buy-button-js

Hello, I did try this, but needed to add a similar config inside a modalProduct object, unfortunately it doesn't appear in the cart. Could you explain how the field is added as a lineItem ?

@rebeccajfriedman Is there any ETA concerning this ? I believe It's quite necessary to add this feature to Buy Button.

arobbins commented 4 years ago

Would love to see this as well!

hunterwebsiteservices commented 4 years ago

Really needing this as well.

jbwhaley commented 4 years ago

Yes, please. This is a huge no-brainer.

hunterwebsiteservices commented 4 years ago

I have been able to use Dave84c's work to build my own solution. Really odd that the Shopify backend supports this, but the buy-button-js code is lacking a few lines of code to pass the data through to the backend.

Here is a link to the compiled JS file to embed on your project. Use it instead of the regular JS file provided by Shopify: https://gist.github.com/feltoar/14125f1138fc44deb4217fc416c3a35d

That won't be enough to get it to work. Since you need to edit your template HTML. However at least you won't need to do any compiling.

So to edit your template HTML, just follow the Shopify Buy Now Button documentation: http://shopify.github.io/buy-button-js/advanced/

For example inside the createComponent object.

options: {
    lineItem: {
        templates: {
            customAttributes: '{{#data.customAttributes}}<div><small>{{key}}: {{value}}</small></div>{{/data.customAttributes}}'
        },
        contents: {
            customAttributes: true
        },
        order: [
            'image',
            'title',
            'variantTitle',
            'customAttributes',
            'price',
            'priceWithDiscounts',
            'quantity',
        ],
    },
    product: {
        contents: {
            properties: true,
        },
        templates: {
            properties: '<input type="text" id="engraving" name="properties[Engraving]" />'
        },
        order: [
            'img',
            'title',
            'price',
            'quantity',
            'options',
            'properties',
            'button',
        ],
    },
},

What this code does is it adds a new template called "properties" to the product template. Customise the HTML as needed. It will look strange without additional styles. Plus you will likely want to add a label, or change the input to select.

Make sure the form fields are all name="properties[PropertyName]" as this is what the compiled code looks for. It only looks for properties.

The second step changes the cart template shows the properties. {{#data.customAttributes}} is a Mustache.js loop that goes through all of the properties[] on the previous template. So you can add as many as you want.

gracinwjohnson commented 4 years ago

We tried this method but kept receiving the error "ShopifyBuy.UI.onReady is not a function." Did you work off our Dave84c's repository to create this?

Desperate to get something to work - it's so frustrating that Shopify doesn't allow an easier way.

hunterwebsiteservices commented 4 years ago

@gracinwjohnson It sounds like your code is not complete. The code I provided is only what goes into the options parameter for ui.createComponent. You still need to do all the other code as per Shopify documentation. Which will be different for every store. See their example file: https://github.com/Shopify/buy-button-js/blob/master/index.example.html

gracinwjohnson commented 4 years ago

I was able to customize the line items in the product page. However, now I'm needing to pass those input to the cart view and I want it to be passed to the backend for order details, emails, etc.

hunterwebsiteservices commented 4 years ago

The code provided should show line item properties in the cart as well as the Shopify back end.

I am in the middle of building a solution for a client, and just discovered there is an extra step to get line item properties to also appear in the email templates. I have yet to do it yet. But these instructions should work: https://community.shopify.com/c/Shopify-Design/Product-pages-Get-customization-information-for-products/td-p/616503#toc-hId-287417639

But you will need the buy now button successfully adding line item properties to the cart and order first before bothering to get them appearing in emails.

gracinwjohnson commented 4 years ago

What's the best way to embed your js file? When I replace the shopify js link with yours, I'm getting a Cross-Origin Read Blocking (CORB) error and "Uncaught ReferenceError: ShopifyBuy is not defined at HTMLScriptElement.ShopifyBuyInit." The line items are showing up on the front end, the inputs are just not passing through in the order.

gracinwjohnson commented 4 years ago

We are tracking this issue in our backlog. We will follow up here when we have an update.

Any update on this @rebeccajfriedman ?

gracinwjohnson commented 4 years ago

What's the best way to embed your js file? When I replace the shopify js link with yours, I'm getting a Cross-Origin Read Blocking (CORB) error and "Uncaught ReferenceError: ShopifyBuy is not defined at HTMLScriptElement.ShopifyBuyInit." The line items are showing up on the front end, the inputs are just not passing through in the order.

@feltoar I cannot find a way to embed your JS file. Any idea as to what I'm doing wrong? I've made the HTML edits and the line item properties are appearing on the front end, the inputs are just not in the cart or passing through in the order.

MLDMoritz commented 4 years ago

Really would love to see this, as this has been implemented already it should be no big deal.

Mr-Newlove commented 3 years ago

I am also having trouble getting this to actually pass the extra properties data field to the Shopify checkout, even when copying the above code.

RiccaD commented 3 years ago

I found out that my Problem with @feltoar steps was the inclusion of his custom script in my code. A normal script tag with the link did not work for some reason. What I did was copying the whole script in a local file. And all of a sudden everything worked perfectly! Maybe that helps you guys @Mr-Newlove @gracinwjohnson

mahlingam commented 3 years ago

I am using custom attributes for a while now with buy-button-js. I created this PR https://github.com/Shopify/buy-button-js/pull/746 to maybe get this feature included in the main stream. That way I would not have to patch it on every release update.

sanjay-makwana-avidbrio commented 3 years ago

In the meantime, if it's urgent, you can grab it here. Made a fork with custom attributes working. See index files for examples: https://github.com/Dave84c/buy-button-js

can I use it on any Shopify theme?

sanjay-makwana-avidbrio commented 3 years ago

I have been able to use Dave84c's work to build my own solution. Really odd that the Shopify backend supports this, but the buy-button-js code is lacking a few lines of code to pass the data through to the backend.

Here is a link to the compiled JS file to embed on your project. Use it instead of the regular JS file provided by Shopify: https://gist.github.com/feltoar/14125f1138fc44deb4217fc416c3a35d

That won't be enough to get it to work. Since you need to edit your template HTML. However at least you won't need to do any compiling.

So to edit your template HTML, just follow the Shopify Buy Now Button documentation: http://shopify.github.io/buy-button-js/advanced/

For example inside the createComponent object.

options: {
  lineItem: {
      templates: {
          customAttributes: '{{#data.customAttributes}}<div><small>{{key}}: {{value}}</small></div>{{/data.customAttributes}}'
      },
      contents: {
          customAttributes: true
      },
      order: [
          'image',
          'title',
          'variantTitle',
          'customAttributes',
          'price',
          'priceWithDiscounts',
          'quantity',
      ],
  },
  product: {
      contents: {
          properties: true,
      },
      templates: {
          properties: '<input type="text" id="engraving" name="properties[Engraving]" />'
      },
      order: [
          'img',
          'title',
          'price',
          'quantity',
          'options',
          'properties',
          'button',
      ],
  },
},

What this code does is it adds a new template called "properties" to the product template. Customise the HTML as needed. It will look strange without additional styles. Plus you will likely want to add a label, or change the input to select.

Make sure the form fields are all name="properties[PropertyName]" as this is what the compiled code looks for. It only looks for properties.

The second step changes the cart template shows the properties. {{#data.customAttributes}} is a Mustache.js loop that goes through all of the properties[] on the previous template. So you can add as many as you want.

@feltoar Unexpected character # in "{{#data.customAttributes}}" can you please share the full solution

Thanks in Advance

jjjoern commented 3 years ago

Are there any news on this topic? Has anyone a working JS file to embed?

RiccaD commented 3 years ago

@jjjoern feltoar Code and js file works for me. Have you tried his? I yes, why isn't it working for you?

jjjoern commented 3 years ago

I tried embedding the JS file this way: var scriptURL = 'https://gist.githubusercontent.com/feltoar/14125f1138fc44deb4217fc416c3a35d/raw/5c19af4d2d9dc1d267a41141555583fe38e2f46b/buy-now-button.js;' And keep receiving this error: "ShopifyBuy.UI.onReady is not a function."

How did you store the JS Script locally?

mikeeus commented 3 years ago

I tried embedding the JS file this way: var scriptURL = 'https://gist.githubusercontent.com/feltoar/14125f1138fc44deb4217fc416c3a35d/raw/5c19af4d2d9dc1d267a41141555583fe38e2f46b/buy-now-button.js;' And keep receiving this error: "ShopifyBuy.UI.onReady is not a function."

How did you store the JS Script locally?

You need to change your Buy button script to not use the onReady callback. Instead init the client and use the returned object directly like this:

var client = ShopifyBuy.buildClient({
  domain: 'shop.myshopify.com',
  storefrontAccessToken: '1234',
});
var ui = ShopifyBuy.UI.init(client);
ui.createComponent('product', {
mikeeus commented 3 years ago

@feltoar Thanks a lot for sharing your solution! It works well for me except the {{#data.customAttributes}} loop isn't showing anything in the lineItem template. Does it work for you?

hunterwebsiteservices commented 3 years ago

I feel kinda bad for the people who need additional help. The solution I provided is very brief and apparently causing confusion.

You need a skilled web developer following Shopify's official documentation in order to get it to work. It's implementation is unique to each individual website, and a high level of familiarity with HTML and Javascript is required.

There's some assumed knowledge. Such as, I had assumed people would know how to host the Javascript code themselves. How to hook it into the javascript life cycle of a website. As well as I had assumed that they would know how to add the display of the properties to the template's HTML (it's in the Shopify documentation I linked).

I feel that detailing these things, which are either explained in Shopify's documentation, or a skilled web developer would already know falls outside the scope of a Github reply.

I would like to also add, with this solution it is not possible to add a file upload property (easily). I've had some requests for this via PM. The Shopify backend supports only text values. So a file upload is not possible without great effort. You would need to have an upload performed entirely in the background via Javascript to a third party, with a resulting (public facing) URL being returned and then inserted as the line item. A non-trivial thing to do.

@mikeeus As per my post way back in 2020.

That won't be enough to get it to work. Since you need to edit your template HTML. However at least you won't need to do any compiling.

So to edit your template HTML, just follow the Shopify Buy Now Button documentation: http://shopify.github.io/buy-button-js/advanced/

mikeeus commented 3 years ago

Thanks for the reply, it turns out my issue was just a typo in my loop so I should have done more to troubleshoot before asking.

I agree with you, there's a lot that people need to do to get this working and its not trivial. I don't think its your responsibility to provide all of that information either. I appreciate you posting your solution though, it was a great starting point for me and I was able to dig into the buy button code and customize it even further.

oappso commented 2 years ago

https://gist.githubusercontent.com/feltoar/14125f1138fc44deb4217fc416c3a35d/raw/5c19af4d2d9dc1d267a41141555583fe38e2f46b/buy-now-button.js is no longer available, does anyone have a link? Thank you.

hunterwebsiteservices commented 2 years ago

Renamed my account:

https://gist.githubusercontent.com/hunterwebsiteservices/14125f1138fc44deb4217fc416c3a35d/raw/5c19af4d2d9dc1d267a41141555583fe38e2f46b/buy-now-button.js

oappso commented 2 years ago

Many thanks!

edalzell commented 2 years ago

Sorry if this is an ignorant question but I couldn't find the answer elsewhere.

I've got the customize JS loading, but how do I pass the custom attributes in? I'm using a "standard" product component w/ an Add to Cart Button and a "standard" cart (slides out).

Or are they defined on the product? If so, where do I set them?

wanderingjam commented 1 year ago

Anyone have an updated version of this for new API version?

Absolutely wild to me that this hasn't been picked up by Shopify yet...

@rebeccajfriedman

TaylorTheDeveloper commented 4 months ago

@wanderingjam I was looking to do the same thing. For others looking for this, I have forked and compiled a library with support for custom attributes so others can learn how to do this. https://github.com/Innovation-Magic-LLC/buy-button-js-customattributes

jacobkossman commented 1 month ago

I was looking to do the same thing. For others looking for this, I have forked and compiled a library with support for custom attributes so others can learn how to do this. https://github.com/Innovation-Magic-LLC/buy-button-js-customattributes

@TaylorTheDeveloper thanks for this! i'm wondering if there's a "proper" function in your code I missed to update the attributes (e.g. from a user input onchange event etc) or if just setting the customAttributes property directly in the "ui.components.product" object is the right way?