reservations@purelytravel.co.uk
0844 80 444 80
Home
About Us
Terms & conditions
Our Service
Privacy Policy
By Road Tours
By River Tours
By Rail Tours
Destinations
Australia
Canada
Canadian Rockies
Eastern Canada
Western Canada
Europe
Christmas Markets
Austria
Belgium
Croatia
Czech Republic
Denmark
Finland
France
Germany
Greece
Greenland
Hungary
Iceland
Italy
Luxemburg
Malta
Monaco
Montenegro
Netherlands
Norway
Poland
Portugal
Spain
Sweden
Switzerland
New Zealand
United Kingdom & Ireland
England
Ireland
Scotland
Wales
USA
Alaska
Eastern USA
Hawaii
Midwest
National Parks
New England
Pacific Northwest
Southern USA
Southwestern
Western USA
Contact us...
Open main menu
Close menu
Home
About Us
Terms & conditions
Our Service
Privacy Policy
By Road Tours
By River Tours
By Rail Tours
Destinations
Australia
Canada
Canadian Rockies
Eastern Canada
Western Canada
Europe
Christmas Markets
Austria
Belgium
Croatia
Czech Republic
Denmark
Finland
France
Germany
Greece
Greenland
Hungary
Iceland
Italy
Luxemburg
Malta
Monaco
Montenegro
Netherlands
Norway
Poland
Portugal
Spain
Sweden
Switzerland
New Zealand
United Kingdom & Ireland
England
Ireland
Scotland
Wales
USA
Alaska
Eastern USA
Hawaii
Midwest
National Parks
New England
Pacific Northwest
Southern USA
Southwestern
Western USA
Contact us...
reservations@purelytravel.co.uk
0844 80 444 80
Home
contact us...
Contact us...
{"time":1761675782303,"blocks":[{"id":"FtR99BMCJd","type":"image","data":{"url":"https:\/\/media.tripcart.com\/images\/2126\/web_1769674427_669393_9555_85_2600x1263.webp","caption":"","alt":"Purely Escorted Tours Resized","width":1063,"height":516,"withBorder":false,"withBackground":false,"stretched":false}},{"id":"JXOrG2h4lq","type":"header","data":{"text":"To make a booking, or for any other questions Please call us on - 0844 80 444 80 or email us...","level":3}},{"id":"3Hx8zaQ1VI","type":"customForm","data":{"customFormId":3720,"html":"<style>\n .g-recaptcha + div:empty {\n display: none;\n }\n @media (max-width: 400px) {\n .g-recaptcha >div {\n width: 100% !important;\n }\n .g-recaptcha iframe {\n width: 100% !important;\n }\n }\n<\/style>\n<div\n x-data=\"customFormHandler('CustomForm3720', 'https:\/\/purely-escorted-tours.ontripcart.com\/page-form')\"\n class=\"custom-form-wrapper\"\n>\n \n <template x-if=\"submitted\">\n <div class=\"flex items-center justify-center gap-2 text-base-100 p-2 md:p-4 bg-[#ECFDF3] rounded-lg border border-[#17B26A]\">\n <span class=\"block icon-no-stroke\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n<rect width=\"20\" height=\"20\" rx=\"8\" fill=\"#17B26A\"\/>\n<g clip-path=\"url(#clip0_6001_40)\">\n<path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M10 3C6.13906 3 3 6.13906 3 10C3 13.8609 6.13906 17 10 17C13.8609 17 17 13.8609 17 10C17 6.13906 13.8609 3 10 3Z\" fill=\"white\"\/>\n<path d=\"M8.65195 13.2019C7.75781 12.3078 6.86914 11.4054 5.97227 10.5113C5.87383 10.4129 5.87383 10.2488 5.97227 10.1504L7.00313 9.11951C7.10156 9.02107 7.26563 9.02107 7.36406 9.11951L8.83789 10.5933L12.6277 6.80076C12.7289 6.70232 12.8902 6.70232 12.9914 6.80076L14.025 7.83435C14.1262 7.93552 14.1262 8.09685 14.025 8.19529L9.01289 13.2019C8.91445 13.3031 8.75313 13.3031 8.65195 13.2019Z\" fill=\"#17B26A\"\/>\n<\/g>\n<defs>\n<clipPath id=\"clip0_6001_40\">\n<rect width=\"14\" height=\"14\" fill=\"white\" transform=\"translate(3 3)\"\/>\n<\/clipPath>\n<\/defs>\n<\/svg>\n <\/span>\n <p class=\"text-tc_base\" x-text=\"successMessage\"><\/p>\n <\/div>\n <\/template>\n\n \n <form\n x-show=\"!submitted\"\n action=\"https:\/\/purely-escorted-tours.ontripcart.com\/page-form\"\n class=\"custom_form\"\n method=\"POST\"\n id=\"CustomForm3720\"\n @submit.prevent=\"submitForm\"\n >\n <input type=\"hidden\" name=\"_token\" value=\"Utj2MhaSoTd2jna3hdWqMvrhSbLMguvMWfwx9Acm\" autocomplete=\"off\"> <input\n type=\"hidden\"\n name=\"custom_form_id\"\n value=\"3720\"\n \/>\n <div class=\"flex gap-4\">\n <div class=\"flex-1 p-4 md:p-8 bg-base-10 rounded-lg border border-base-30 space-y-4 md:space-y-6\">\n <div>\n <div class=\"\">\n <label class=\"text-tc_xs font-semibold text-base-100\">\n Name\n <\/label>\n <span class=\"text-alert-red ml-0.5 text-tc_xs\">*<\/span>\n <\/div>\n <input\n type=\"text\"\n value=\"\"\n placeholder=\"Enter your name\"\n class=\"w-full mt-2 rounded shadow-1 h-11 border border-base-30 text-base-100 placeholder-base-40 text-tc_xs py-2.5 px-4\"\n name=\"name\"\n required \/>\n \n \n \n \n \n \n <\/div>\n <div>\n <div class=\"\">\n <label class=\"text-tc_xs font-semibold text-base-100\">\n Email\n <\/label>\n <span class=\"text-alert-red ml-0.5 text-tc_xs\">*<\/span>\n <\/div>\n <input\n type=\"email\"\n value=\"\"\n placeholder=\"Enter your email\"\n class=\"w-full mt-2 rounded shadow-1 h-11 border border-base-30 text-base-100 placeholder-base-40 text-tc_xs py-2.5 px-4\"\n name=\"email\"\n required \/>\n \n \n \n \n \n \n <\/div>\n <div>\n <div class=\"\">\n <label class=\"text-tc_xs font-semibold text-base-100\">\n Contact Number\n <\/label>\n <span class=\"text-alert-red ml-0.5 text-tc_xs\">*<\/span>\n <\/div>\n <input\n type=\"phone\"\n value=\"\"\n placeholder=\"\"\n class=\"w-full mt-2 rounded shadow-1 h-11 border border-base-30 text-base-100 placeholder-base-40 text-tc_xs py-2.5 px-4\"\n name=\"contact-number\"\n required \/>\n \n \n \n \n \n \n <\/div>\n <div>\n <div class=\"\">\n <label class=\"text-tc_xs font-semibold text-base-100\">\n Subject\n <\/label>\n <span class=\"text-alert-red ml-0.5 text-tc_xs\">*<\/span>\n <\/div>\n <input\n type=\"text\"\n value=\"\"\n placeholder=\"Enter your subject\"\n class=\"w-full mt-2 rounded shadow-1 h-11 border border-base-30 text-base-100 placeholder-base-40 text-tc_xs py-2.5 px-4\"\n name=\"subject\"\n required \/>\n \n \n \n \n \n \n <\/div>\n <div>\n <div class=\"\">\n <label class=\"text-tc_xs font-semibold text-base-100\">\n Message\n <\/label>\n <span class=\"text-alert-red ml-0.5 text-tc_xs\">*<\/span>\n <\/div>\n \n <textarea\n class=\"w-full mt-2 border text-tc_xs placeholder:text-base-40 border-base-30 rounded small-scroll shadow-1 py-2.5 px-4 resize-none min-h-[80px]\"\n placeholder=\"Enter your message\"\n name=\"message\"\n required ><\/textarea>\n \n \n \n \n \n <\/div>\n \n \n \n \n <div x-show=\"errorMessage\" x-cloak class=\"text-alert-red text-tc_xs mt-2\" x-text=\"errorMessage\"><\/div>\n\n \n <button\n type=\"submit\"\n class=\"py-3 px-6 tour-btn inline-flex items-center gap-3 text-center leading-4 group rounded-lg border-2 font-medium transition-all text-tc_sm text-[rgb(var(--white-color))] bg-[rgb(var(--primary-color-100))] border-[rgb(var(--primary-color-100))] hover:bg-[rgb(var(--white-color))] hover:text-[rgb(var(--primary-color-100))] hover:border-[rgb(var(--primary-color-100))] disabled:opacity-50 disabled:cursor-not-allowed disabled:pointer-events-none\"\n :disabled=\"isSubmitting\"\n :class=\"{ 'opacity-50 cursor-not-allowed pointer-events-none': isSubmitting }\"\n >\n Submit\n <span x-show=\"isSubmitting\">\n <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z\" opacity=\"0.25\"\/><path fill=\"currentColor\" d=\"M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z\"><animateTransform attributeName=\"transform\" dur=\"0.75s\" repeatCount=\"indefinite\" type=\"rotate\" values=\"0 12 12;360 12 12\" \/><\/path><\/svg>\n <\/span>\n <\/button>\n <\/div>\n <\/div>\n<\/form>\n<\/div>\n\n<script>\n \/**\n * Custom Form Handler - Alpine.js Component\n * Handles form submission without page reload using native fetch API\n * Shows success message after submission until page refresh\n *\/\n if (typeof window.customFormHandler === 'undefined') {\n window.customFormHandler = function(formId, actionUrl) {\n return {\n formId: formId,\n actionUrl: actionUrl,\n isSubmitting: false,\n submitted: false,\n successMessage: '',\n errorMessage: '',\n\n \/**\n * Submit form via fetch API\n * On success: hides form and shows success message\n * On error: shows error message and resets reCAPTCHA if available\n *\/\n async submitForm() {\n \/\/ Prevent double submission\n if (this.isSubmitting) return;\n\n this.isSubmitting = true;\n this.errorMessage = '';\n\n const form = document.getElementById(this.formId);\n if (!form) {\n this.isSubmitting = false;\n return;\n }\n\n const formData = new FormData(form);\n const self = this;\n\n \/\/ Get reCAPTCHA token for explicitly rendered widgets (v2-checkbox)\n const recaptchaToken = this.getRecaptchaToken(form);\n if (recaptchaToken) {\n formData.set('g-recaptcha-response', recaptchaToken);\n }\n\n try {\n const response = await fetch(this.actionUrl, {\n method: 'POST',\n body: formData,\n headers: {\n 'X-Requested-With': 'XMLHttpRequest',\n 'Accept': 'application\/json'\n }\n });\n\n const data = await response.json();\n\n if (response.ok && data.status) {\n \/\/ Check if redirect is required\n form.reset();\n if (data.submission_action === 'redirect' && data.redirect_url) {\n \/\/ Redirect to the provided URL\n window.location.href = data.redirect_url;\n } else {\n \/\/ Default behavior - show message and hide form\n self.successMessage = data.message;\n self.submitted = true;\n }\n } else {\n \/\/ Error - show validation errors or message\n self.handleErrors(data);\n self.safeResetRecaptcha();\n }\n } catch (error) {\n console.error('Form submission error:', error);\n self.errorMessage = 'Something went wrong. Please try again.';\n self.safeResetRecaptcha();\n } finally {\n \/\/ Always re-enable the button after submission completes\n self.isSubmitting = false;\n }\n },\n\n \/**\n * Get reCAPTCHA token from explicitly rendered widget\n *\/\n getRecaptchaToken: function(form) {\n if (typeof grecaptcha === 'undefined') return null;\n\n try {\n const recaptchaWidget = form.querySelector('.g-recaptcha[data-sitekey]');\n if (!recaptchaWidget) return null;\n\n \/\/ Check if widget was explicitly rendered (has data-widget-id)\n const widgetId = recaptchaWidget.getAttribute('data-widget-id');\n if (widgetId !== null) {\n return grecaptcha.getResponse(parseInt(widgetId, 10));\n }\n\n \/\/ For auto-rendered widgets, try getting response without widget ID\n if (recaptchaWidget.querySelector('iframe') || recaptchaWidget.getAttribute('data-rendered')) {\n return grecaptcha.getResponse();\n }\n } catch (e) {\n console.debug('Could not get reCAPTCHA token:', e.message);\n }\n\n return null;\n },\n\n \/**\n * Handle error response from server\n *\/\n handleErrors: function(data) {\n if (data && data.errors && typeof data.errors === 'object') {\n const keys = Object.keys(data.errors);\n if (keys.length > 0) {\n const firstError = data.errors[keys[0]];\n if (Array.isArray(firstError)) {\n this.errorMessage = firstError[0];\n } else {\n this.errorMessage = String(firstError);\n }\n return;\n }\n }\n this.errorMessage = (data && data.message) ? data.message : 'Something went wrong. Please try again.';\n },\n\n \/**\n * Safely reset reCAPTCHA widget if it exists\n *\/\n safeResetRecaptcha: function() {\n if (typeof grecaptcha === 'undefined') return;\n\n try {\n const form = document.getElementById(this.formId);\n if (!form) return;\n\n const recaptchaWidget = form.querySelector('.g-recaptcha[data-sitekey]');\n if (!recaptchaWidget) return;\n\n \/\/ Check if widget was explicitly rendered (has data-widget-id)\n const widgetId = recaptchaWidget.getAttribute('data-widget-id');\n if (widgetId !== null) {\n grecaptcha.reset(parseInt(widgetId, 10));\n } else if (recaptchaWidget.querySelector('iframe') || recaptchaWidget.getAttribute('data-rendered')) {\n grecaptcha.reset();\n }\n } catch (e) {\n \/\/ Silently ignore\n }\n },\n\n \/**\n * Submit form with reCAPTCHA token (for v3 and v2-invisible)\n *\/\n submitWithToken: function(token) {\n const form = document.getElementById(this.formId);\n if (!form) return;\n\n let tokenInput = form.querySelector('input[name=\"g-recaptcha-response\"]');\n if (!tokenInput) {\n tokenInput = document.createElement('input');\n tokenInput.type = 'hidden';\n tokenInput.name = 'g-recaptcha-response';\n form.appendChild(tokenInput);\n }\n tokenInput.value = token;\n this.submitForm();\n }\n };\n };\n }\n\n \/\/ Global callback for reCAPTCHA v3\/v2-invisible\n window['onSubmitCustomForm3720'] = function(token) {\n const formEl = document.getElementById('CustomForm3720');\n if (!formEl) return;\n const wrapper = formEl.closest('.custom-form-wrapper');\n if (wrapper && wrapper._x_dataStack && wrapper._x_dataStack[0]) {\n wrapper._x_dataStack[0].submitWithToken(token);\n }\n };\n<\/script>\n"}}],"version":"2.31.0-rc.7"}
300" >