diff --git a/doc/user/events/widget.rst b/doc/user/events/widget.rst index 5d5e18294d..040567c74b 100644 --- a/doc/user/events/widget.rst +++ b/doc/user/events/widget.rst @@ -293,6 +293,16 @@ with that information:: This works for the pretix Button as well, if you also specify a product. + +As data-attributes are reactive, you can change them with JavaScript as well. Please note, that once the user +started the checkout process, we do not update the data-attributes in the existing checkout process to not +interrupt the checkout UX. + +When updating data-attributes through JavaScript, make sure you do not have a stale reference to the HTMLNode of the +widget. When the widget is created, the original HTMLNode can happen to be replaced. So make sure to always have a +fresh reference like so +``document.querySelectorAll("pretix-widget, pretix-button, .pretix-widget-wrapper")`` + Currently, the following attributes are understood by pretix itself: * ``data-email`` will pre-fill the order email field as well as the attendee email field (if enabled). @@ -329,125 +339,72 @@ Hosted or pretix Enterprise are active, you can pass the following fields: * If you use the campaigns plugin, you can pass a campaign ID as a value to ``data-campaign``. This way, all orders made through this widget will be counted towards this campaign. -* If you use the tracking plugin, you can enable cross-domain tracking. To do so, you need to initialize the - pretix-widget manually. Use the html code to embed the widget and add one the following code snippets. Make sure to - replace all occurrences of with your Google Analytics MEASUREMENT_ID (UA-XXXXXXX-X or G-XXXXXXXX) +* If you use the tracking plugin, you can enable cross-domain tracking. Please note: when you run your pretix-shop on a + subdomain of your main tracking domain, then you do not need cross-domain tracking as tracking automatically works + across subdomains. See :ref:`custom_domain` for how to set this up. - Please also make sure to add the embedding website to your `Referral exclusions + Please make sure to add the embedding website to your `Referral exclusions `_ in your Google Analytics settings. - If you use Google Analytics 4 (GA4 – G-XXXXXXXX):: + Add Google Analytics as you normally would with all your `window.dataLayer` and `gtag` configurations. Also add the + widget code normally. Then you have two options: - - + + * Or asynchronously set data-attributes – the widgets are shown immediately, but once the user has started checkout, + data-attributes are not updated. Make sure to replace all occurrences of with your Google + Analytics MEASUREMENT_ID (G-XXXXXXXX) + + - - If you use Universal Analytics with ``gtag.js`` (UA-XXXXXXX-X):: - - - - - If you use ``analytics.js`` (Universal Analytics):: - - - + .. _Let's Encrypt: https://letsencrypt.org/ diff --git a/src/pretix/static/pretixpresale/js/widget/widget.js b/src/pretix/static/pretixpresale/js/widget/widget.js index e63392353d..84a42b81d2 100644 --- a/src/pretix/static/pretixpresale/js/widget/widget.js +++ b/src/pretix/static/pretixpresale/js/widget/widget.js @@ -1911,8 +1911,19 @@ var create_widget = function (element) { } } + var observer = new MutationObserver((mutationList) => { + mutationList.forEach((mutation) => { + if (mutation.type == "attributes" && mutation.attributeName.startsWith("data-")) { + Vue.set(app.widget_data, mutation.attributeName.substring(5), mutation.target.getAttribute(mutation.attributeName)); + } + }); + }); + var observerOptions = { attributes: true }; + if (element.tagName !== "pretix-widget") { element.innerHTML = ""; + // we need to watch the container as well as the replaced root-node (see mounted()) + observer.observe(element, observerOptions); } var app = new Vue({ @@ -1970,6 +1981,9 @@ var create_widget = function (element) { created: function () { this.reload(); }, + mounted: function () { + observer.observe(this.$el, observerOptions); + }, computed: shared_root_computed, methods: shared_root_methods }); @@ -1996,8 +2010,19 @@ var create_button = function (element) { } } + var observer = new MutationObserver((mutationList) => { + mutationList.forEach((mutation) => { + if (mutation.type == "attributes" && mutation.attributeName.startsWith("data-")) { + Vue.set(app.widget_data, mutation.attributeName.substring(5), mutation.target.getAttribute(mutation.attributeName)); + } + }); + }); + var observerOptions = { attributes: true }; + if (element.tagName !== "pretix-button") { element.innerHTML = "" + element.innerHTML + ""; + // Vue does not replace the container, so watch container as well + observer.observe(element, observerOptions); } var itemsplit = raw_items.split(","); @@ -2030,6 +2055,9 @@ var create_button = function (element) { }, created: function () { }, + mounted: function () { + observer.observe(this.$el, observerOptions); + }, computed: shared_root_computed, methods: shared_root_methods });