Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
napter opened this issue Jan 18, 2019 · 39 comments
Open

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

napter opened this issue Jan 18, 2019 · 39 comments

Comments

@napter
Copy link

napter commented Jan 18, 2019

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
Copy link
Author

napter commented Jan 22, 2019

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
Copy link
Contributor

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

@hyunilmmt
Copy link

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

@Dave84c
Copy link

Dave84c commented Mar 25, 2019

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
Copy link

any update on this?

@mizujin
Copy link

mizujin commented May 1, 2020

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
Copy link

arobbins commented May 1, 2020

Would love to see this as well!

@hunterwebsiteservices
Copy link

Really needing this as well.

@jbwhaley
Copy link

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

@hunterwebsiteservices
Copy link

hunterwebsiteservices commented Jun 2, 2020

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
Copy link

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
Copy link

@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
Copy link

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
Copy link

hunterwebsiteservices commented Jun 4, 2020

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
Copy link

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
Copy link

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

Any update on this @rebeccajfriedman ?

@gracinwjohnson
Copy link

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
Copy link

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

@Mr-Newlove
Copy link

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
Copy link

RiccaD commented Dec 9, 2020

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
Copy link

I am using custom attributes for a while now with buy-button-js. I created this PR #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
Copy link

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
Copy link

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
Copy link

jjjoern commented Apr 12, 2021

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

@RiccaD
Copy link

RiccaD commented Apr 12, 2021

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

@jjjoern
Copy link

jjjoern commented Apr 12, 2021

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
Copy link

mikeeus commented Jul 31, 2021

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
Copy link

mikeeus commented Jul 31, 2021

@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
Copy link

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
Copy link

mikeeus commented Aug 1, 2021

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
Copy link

oappso commented Sep 23, 2021

@oappso
Copy link

oappso commented Sep 23, 2021

Many thanks!

@edalzell
Copy link

edalzell commented Apr 19, 2022

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
Copy link

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
Copy link

@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
Copy link

jacobkossman commented Jul 22, 2024

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?

@wturnerharris
Copy link

+1 on this 5-year-running issue. Thanks to @TaylorTheDeveloper for your fork, which made it that much easier to prototype this.

Was really just trying to build a gifting flow per #860 with custom line item attributes for gifts.

@TaylorTheDeveloper
Copy link

TaylorTheDeveloper commented Nov 9, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests