diff --git a/.eleventy.js b/.eleventy.js index 533264e8e3..3630c618e7 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -656,26 +656,6 @@ module.exports = function(eleventyConfig) { } }); - eleventyConfig.addShortcode("hubspotForm", function(formId, cta, reference, functionName = 'displayHubSpotForm') { - return ` - - - `; - }); - eleventyConfig.addPairedShortcode("navoption", function(content, label, link, depth, icon, iconSolid, addClasses) { let svg, iconSvg = '', classes, chevron if (icon) { diff --git a/src/_includes/base.js b/src/_includes/base.js index 0db68370f2..d0536fc383 100644 --- a/src/_includes/base.js +++ b/src/_includes/base.js @@ -67,16 +67,100 @@ document.createElement = function(...args) { function hsFallback (element) { if (element && element.parentNode) { + const existingFallback = element.parentNode.querySelector('.ff-hubspot-consent-fallback') + if (existingFallback) { + existingFallback.classList.remove('hidden') + return + } + const errorSection = document.createElement('section'); - errorSection.classList.add('text-center', 'border', 'border-indigo-300', 'rounded-lg', 'bg-white', 'px-4'); + errorSection.classList.add('ff-hubspot-consent-fallback'); errorSection.innerHTML = ` -

Hmm… there was supposed to be a form here.

-

- It might be blocked by your browser or privacy settings. Try - , - adjusting your privacy settings, or switching browsers to continue. -

+

Unable to load HubSpot content.

`; element.parentNode.insertBefore(errorSection, element.nextSibling); } } + +function loadHubSpotFormsScript () { + if (window.hbspt?.forms?.create) { + return Promise.resolve(window.hbspt) + } + + if (window._ffHubSpotFormsPromise) { + return window._ffHubSpotFormsPromise + } + + window._ffHubSpotFormsPromise = new Promise((resolve, reject) => { + const existing = document.getElementById('ff-hs-forms-script') + + if (existing) { + existing.addEventListener('load', () => resolve(window.hbspt), { once: true }) + existing.addEventListener('error', () => reject(new Error('HubSpot forms script failed to load')), { once: true }) + return + } + + const script = document.createElement('script') + script.id = 'ff-hs-forms-script' + script.async = true + script.charset = 'utf-8' + script.src = 'https://js-eu1.hsforms.net/forms/embed/v2.js' + script.onload = () => resolve(window.hbspt) + script.onerror = () => reject(new Error('HubSpot forms script failed to load')) + document.head.appendChild(script) + }).catch((err) => { + window._ffHubSpotFormsPromise = null + throw err + }) + + return window._ffHubSpotFormsPromise +} + +function ffCreateHubSpotForm (config) { + if (!config || !config.formId) { + return + } + + const targetElement = config.target ? document.querySelector(config.target) : null + const fallbackElement = config.fallbackSelector ? document.querySelector(config.fallbackSelector) : null + if (config.target && !targetElement) { + return + } + + if (targetElement?.dataset.ffHsFormLoaded === 'true') { + return + } + + if (targetElement && targetElement.querySelector('iframe, form, .hbspt-form')) { + targetElement.dataset.ffHsFormLoaded = 'true' + return + } + + loadHubSpotFormsScript().then(() => { + if (!window.hbspt?.forms?.create) { + if (fallbackElement) { + fallbackElement.classList.remove('hidden') + } else if (targetElement) { + hsFallback(targetElement) + } + return + } + // Keep local helper-only keys out of HubSpot's context object. + const { fallbackSelector, ...hubspotConfig } = config + window.hbspt.forms.create(hubspotConfig) + if (targetElement) { + targetElement.dataset.ffHsFormLoaded = 'true' + } + if (fallbackElement) { + fallbackElement.classList.add('hidden') + } + }).catch(() => { + if (fallbackElement) { + fallbackElement.classList.remove('hidden') + } else if (targetElement) { + hsFallback(targetElement) + } + }) +} + +window.ffCreateHubSpotForm = ffCreateHubSpotForm diff --git a/src/_includes/blog/blog-posts.njk b/src/_includes/blog/blog-posts.njk index 888399299f..bea923b004 100644 --- a/src/_includes/blog/blog-posts.njk +++ b/src/_includes/blog/blog-posts.njk @@ -31,7 +31,11 @@
Sign up for our monthly email updates:
- {% include "hubspot/hs-newsletter.njk" %} + {% set formId = "159c173d-dd95-49bd-922b-ff3ef243e90c" %} + {% set cta = "cta-blog-subscribe" %} + {% set reference = "blog" %} + {% set targetId = "hs-form-newsletter-blog" %} + {% include "hubspot/hs-form.njk" %}
{% else %}
  • @@ -58,4 +62,4 @@
  • -{% endif %} \ No newline at end of file +{% endif %} diff --git a/src/_includes/hubspot/consent-fallback.njk b/src/_includes/hubspot/consent-fallback.njk new file mode 100644 index 0000000000..83fedb6b67 --- /dev/null +++ b/src/_includes/hubspot/consent-fallback.njk @@ -0,0 +1,24 @@ + diff --git a/src/_includes/hubspot/hs-book-meeting.njk b/src/_includes/hubspot/hs-book-meeting.njk index 9edccf4ba1..5e2dcb4f44 100644 --- a/src/_includes/hubspot/hs-book-meeting.njk +++ b/src/_includes/hubspot/hs-book-meeting.njk @@ -1,15 +1,6 @@ - +{% set fallbackId = 'meetings-consent-placeholder' %} +{% set contentType = 'meeting calendar' %} +{% include "hubspot/consent-fallback.njk" %} diff --git a/src/_includes/hubspot/hs-form.njk b/src/_includes/hubspot/hs-form.njk index d342f38d16..1f96cd94c6 100644 --- a/src/_includes/hubspot/hs-form.njk +++ b/src/_includes/hubspot/hs-form.njk @@ -1,15 +1,31 @@ +{% set hubspotData = hubspot or {} %} +{% set hubspotFormId = formId or hubspotData.formId %} +{% set formTargetId = targetId or ('hs-form-' + (hubspotFormId | replace('-', ''))) %} +{% set fallbackId = formTargetId + '-fallback' %} +{% set contentType = 'form' %} +{% set hubspotRegion = region or hubspotData.region or 'eu1' %} +{% set hubspotPortalId = portalId or hubspotData.portalId or '26586079' %} +{% set onFormSubmittedHandler = onFormSubmitted or hubspotData.onFormSubmitted %} +{% set ctaValue = cta or hubspotData.cta %} +{% set referenceValue = hubspotData.reference or title %} + +
    +{% include "hubspot/consent-fallback.njk" %} - diff --git a/src/_includes/hubspot/hs-newsletter.njk b/src/_includes/hubspot/hs-newsletter.njk deleted file mode 100644 index 690e249a44..0000000000 --- a/src/_includes/hubspot/hs-newsletter.njk +++ /dev/null @@ -1,13 +0,0 @@ - - diff --git a/src/_includes/migration.njk b/src/_includes/migration.njk index a7bb5e66d6..8fb6b2e182 100644 --- a/src/_includes/migration.njk +++ b/src/_includes/migration.njk @@ -20,8 +20,11 @@ -
    - +
    + {% set formId = "968a9ab6-3dd8-45b2-991c-3f055dc18787" %} + {% set targetId = "hs-user-form" %} + {% set onFormSubmitted = "function () { migrateFile(); }" %} + {% include "hubspot/hs-form.njk" %}
    @@ -113,16 +116,4 @@ event.preventDefault(); } - function displayHubSpotForm() { - hbspt.forms.create({ - target: '#hs-user-form', - region: "eu1", - portalId: "26586079", - formId:"968a9ab6-3dd8-45b2-991c-3f055dc18787", - onFormSubmitted: function ($form) { - migrateFile() - } - }); - } - diff --git a/src/blog/2025/07/certified-nodes-v2.md b/src/blog/2025/07/certified-nodes-v2.md index 080643ef91..e30ef0460d 100644 --- a/src/blog/2025/07/certified-nodes-v2.md +++ b/src/blog/2025/07/certified-nodes-v2.md @@ -2,9 +2,13 @@ title: "Curated Node-RED Integrations: FlowFuse Certified Nodes 2.0" subtitle: "FlowFuse Unveils Certified Nodes Program to Reward Quality and Ensure Long-Term Support" description: "FlowFuse announces Certified Nodes v2.0 - connecting enterprises with the highest quality Node-RED nodes, built and maintained by recognized experts in their fields." +templateEngineOverride: njk,md date: 2025-07-01 authors: ["zeger-jan-van-de-weg"] image: blog/2025/07/images/certified-nodes-v2.png +certificationHubspot: + formId: "6e02fe34-13c3-442b-8c27-9a12e72bba37" + targetId: "hs-form-certified-nodes-contact" tags: - flowfuse - node-red @@ -81,11 +85,8 @@ industry's leading experts. ### Contact us to discuss your node certification - - +{% set formId = certificationHubspot.formId %} +{% set targetId = certificationHubspot.targetId %} +{% set cta = "cta-certified-nodes-contact" %} +{% set reference = "certified-nodes-v2" %} +{% include "hubspot/hs-form.njk" %} diff --git a/src/js/cookieconsent-config.js b/src/js/cookieconsent-config.js index dba8661693..ecfcf1a24f 100644 --- a/src/js/cookieconsent-config.js +++ b/src/js/cookieconsent-config.js @@ -219,7 +219,7 @@ CookieConsent.run({ en: { consentModal: { title: "This site uses cookies", - description: "We use cookies to ensure this site works properly and, with your permission, to improve your experience and enable features like analytics and live chat support.", + description: "We use cookies to ensure this site works properly, forms render properly, and, with your permission, to improve your experience and enable features like analytics and live chat support.", acceptAllBtn: "Accept all", showPreferencesBtn: "Settings", footer: "Privacy Policy\n" @@ -238,7 +238,7 @@ CookieConsent.run({ }, { title: "Strictly Necessary Cookies Always Enabled", - description: "Essential cookies are crucial for the basic functionality of our website. Without these cookies, our website could not function properly.", + description: "Essential cookies are crucial for core website functionality, including security, anti-spam protection (Google reCAPTCHA), and technical form delivery. Without these cookies, key features of the website, such as secure contact forms, could not function properly.", linkedCategory: "necessary" }, { @@ -248,7 +248,7 @@ CookieConsent.run({ }, { title: "Analytics Cookies", - description: "We use tools including Google Analytics, HubSpot, PostHog, and warmly.ai to understand how visitors interact with our website. This category also enables HubSpot meeting embeds and the chat widget.", + description: "We use tools including Google Analytics, HubSpot tracking, PostHog, and warmly.ai to understand how visitors interact with our website. This category enables HubSpot tracking, meeting embeds, and the chat widget.", linkedCategory: "analytics" }, { diff --git a/src/pricing/index.njk b/src/pricing/index.njk index 2ff3c4af59..294dc6a3e4 100644 --- a/src/pricing/index.njk +++ b/src/pricing/index.njk @@ -304,7 +304,13 @@ hubspot: To learn more about our plans, discuss your specific needs, or get advice on the best fit for your project, please fill out the form and we will get back to you as soon as possible.

    - {% hubspotForm hubspot.cloud.formId, hubspot.cloud.cta, hubspot.reference, 'contactUsForm' %} +
    + {% set formId = hubspot.cloud.formId %} + {% set cta = hubspot.cloud.cta %} + {% set reference = hubspot.reference %} + {% set targetId = 'hs-form-pricing-cloud-contact-us' %} + {% include "hubspot/hs-form.njk" %} +
    @@ -320,7 +326,13 @@ hubspot: Unlock the complete potential of FlowFuse with a complimentary 30-day Enterprise license. This trial gives you the chance to explore all the features and functionalities of FlowFuse in your own environment. To start your trial, simply fill out the form. Our sales team will reach out to you to discuss your needs and provide the license.

    - {% hubspotForm hubspot.selfHosted.formId, hubspot.selfHosted.cta, hubspot.reference, 'trialLicenseForm' %} +
    + {% set formId = hubspot.selfHosted.formId %} + {% set cta = hubspot.selfHosted.cta %} + {% set reference = hubspot.reference %} + {% set targetId = 'hs-form-pricing-self-hosted-trial-license' %} + {% include "hubspot/hs-form.njk" %} +