buy-button-js icon indicating copy to clipboard operation
buy-button-js copied to clipboard

Adding line items with custom attributes / line item properties

Open napter opened this issue 6 years ago • 37 comments

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 avatar Jan 18 '19 23:01 napter

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.

napter avatar Jan 22 '19 06:01 napter

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

rebeccajfriedman avatar Jan 30 '19 21:01 rebeccajfriedman

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

hyunilmmt avatar Mar 25 '19 06:03 hyunilmmt

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

Dave84c avatar Mar 25 '19 09:03 Dave84c

any update on this?

reigelgallarde avatar Jan 16 '20 09:01 reigelgallarde

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.

mizujin avatar May 01 '20 04:05 mizujin

Would love to see this as well!

arobbins avatar May 01 '20 13:05 arobbins

Really needing this as well.

hunterwebsiteservices avatar May 01 '20 22:05 hunterwebsiteservices

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

jbwhaley avatar May 22 '20 01:05 jbwhaley

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.

hunterwebsiteservices avatar Jun 02 '20 01:06 hunterwebsiteservices

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.

gracinwjohnson avatar Jun 03 '20 22:06 gracinwjohnson

@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

hunterwebsiteservices avatar Jun 03 '20 23:06 hunterwebsiteservices

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.

gracinwjohnson avatar Jun 04 '20 02:06 gracinwjohnson

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.

hunterwebsiteservices avatar Jun 04 '20 23:06 hunterwebsiteservices

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 avatar Jun 06 '20 02:06 gracinwjohnson

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

Any update on this @rebeccajfriedman ?

gracinwjohnson avatar Jun 10 '20 21:06 gracinwjohnson

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.

gracinwjohnson avatar Jun 10 '20 21:06 gracinwjohnson

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

MLDMoritz avatar Jul 09 '20 22:07 MLDMoritz

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.

Mr-Newlove avatar Oct 28 '20 00:10 Mr-Newlove

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

RiccaD avatar Dec 09 '20 23:12 RiccaD

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.

mahlingam avatar Dec 12 '20 16:12 mahlingam

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 avatar Feb 08 '21 07:02 sanjay-makwana-avidbrio

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

sanjay-makwana-avidbrio avatar Feb 08 '21 07:02 sanjay-makwana-avidbrio

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

jjjoern avatar Apr 12 '21 15:04 jjjoern

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

RiccaD avatar Apr 12 '21 15:04 RiccaD

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?

jjjoern avatar Apr 12 '21 15:04 jjjoern

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 avatar Jul 31 '21 16:07 mikeeus

@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?

mikeeus avatar Jul 31 '21 16:07 mikeeus

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/

hunterwebsiteservices avatar Aug 01 '21 21:08 hunterwebsiteservices

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.

mikeeus avatar Aug 01 '21 21:08 mikeeus