PageSourceSearch

https://www.poa.com.au/

html poa.com.au collected 2026-09-30 06:14:12 UTC 115,505 bytes, 2,390 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en" data-ver="1404">
3<head>
3<script>(function(w,i,g){w[g]=w[g]||[];if(typeof w[g].push=='function')w[g].push(i)})
4(window,'GTM-MS2KK66X','google_tags_first_party');</script>
4<script>(function(w,d,s,l){w[l]=w[l]||[];(function(){w[l].push(arguments);})('set', 'developer_id.dY2E1Nz', true);
5		var f=d.getElementsByTagName(s)[0],
6		j=d.createElement(s);j.async=true;j.src='/ulg8/';
7		f.parentNode.insertBefore(j,f);
8		})(window,document,'script','dataLayer');</script>
8
9	<meta charset="utf-8">
10	<meta name="viewport" content="width=device-width, initial-scale=1.0">
11	<meta name="thumbnail" content="https://os-data-2.s3-ap-southeast-2.amazonaws.com/poa-com-au/images/fbshare.jpg" />
12	<title>POA | Billboard Advertising</title><link rel="shortcut icon" href="/favicon.png" type="image/png" /><meta name="description" content="POA is one of the largest and fastest growing regional advertising organisations in Australia, we bring billboards and digital signage solutions to Cairns, Townsville,  Toowoomba and Brisbane." />
13<meta itemprop="name" content=" POA is one of the largest and fastest growing regional advertising organisations in Australia, we bring billboards and digital signage solutions to Cairns, Townsville,  Toowoomba and Brisbane.  | POA Outdoor Advertising" />
14<meta property="og:description" content="POA is one of the largest and fastest growing regional advertising organisations in Australia, we bring billboards and digital signage solutions to Cairns, Townsville,  Toowoomba and Brisbane." />
15<meta itemprop="name" content=" POA | Billboard Advertising  | POA Outdoor Advertising" />
16<meta property="og:title" content=" POA | Billboard Advertising  | POA Outdoor Advertising" />
17<meta property="og:url" content="https://www.poa.com.au/" />
18<meta property="og:site_name" content=" POA | Billboard Advertising  | POA Outdoor Advertising" />
19<meta property="og:type" content="website"/>
20<link rel="canonical" href="https://www.poa.com.au/" />
21<meta property="fb:admins" content="100003191299389"/>
22<meta property="fb:page_id" content="107330822636013"/>
23<meta itemprop="image" content="https://cdn.xargocdn.com/poa-com-au/d2568c89-cd57-4b51-94d6-b5ff7fb2adf2/ShareImage_original.webp" />
24<meta property="og:image" content="https://cdn.xargocdn.com/poa-com-au/d2568c89-cd57-4b51-94d6-b5ff7fb2adf2/ShareImage_original.webp" />
25<meta name="twitter:image" content="https://cdn.xargocdn.com/poa-com-au/d2568c89-cd57-4b51-94d6-b5ff7fb2adf2/ShareImage_original.webp" />
26<meta name="robots" content="NOODP" />
27		
28		<link href="/templates/oracle/css/home-min.css?ver=1404" rel="stylesheet" type="text/css" />
29<!-- Google Tag Manager -->
30	
30<script nonce="WWpGbVlXTTBZVFUzWVdJNE16QXk=">
vendor: 338 bytes, lines 30-35
30
31	(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
32	new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
33	j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
34	'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
35	})(window,document,'script','dataLayer','
35GTM-MS2KK66X
vendor: 6 bytes, lines 35-36
35');
36	
36</script>
36
37<!-- End Google Tag Manager -->	
38</head>
39<body class=" page-2 template-homepage" data-id="2" data-template="oracle">
40<!-- Google Tag Manager (noscript) -->
41<noscript><iframe src=https://www.googletagmanager.com/ns.html?id=GTM-MS2KK66X
42height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
43<!-- End Google Tag Manager (noscript) -->	<a class="skip-to-content" href="#page-content">Skip to main content</a>
44	<div class="section-countdown">
45		<div class="wrapper">
46			<div class="title">
47				<span>
48					We have some<br />
49					<span>Big News</span> <span>Coming...</span>
50				</span>
51			</div>
52			<div class="countdown">
53				<div class="box">
54					<span>0-329</span>
55					<span>Days<br />To Go</span>
56				</div>
57				<div class="img">
58					<img loading="lazy" src="/templates/oracle/img/countdown.webp" alt="Big news countdown" />
59				</div>
60			</div>
61		</div>
62	</div>
63
64	<header class="contrast-inverted header--v10">
65		<div class="header--v10-bg">
66			<img src="/templates/oracle/img/header--v10-bg.webp" alt="Header background" />
67		</div>
68		<div class="header--v10-top">
69			<div class="wrapper">
70				<a href="https://www.poa.com.au/" class="header--v10-logo">
71					<img src="/templates/oracle/img/header--v10-logo-mobile.svg?ver=123" alt="Header logo Mobile" />
72					<img src="/templates/oracle/img/header--v10-logo.svg" alt="Header logo" />
73				</a>
74			</div>
75						<div class="header--v10-neon">
76				<img src="https://www.poa.com.au/templates/oracle/img/header--v10-neon.webp" alt="Header neon" />
77				<a class="header-v10__neon-text" href="https://www.poa.com.au/join-our-crew/" >
78 
79					<span class="item-title">Love Sales? </span>
80					<span class="item-subtitle">Apply Here</span>
81			
82				</a>	
83			</div>
84		</div>
85		<div class="header--v10-bottom">
86			<div class="wrapper">
87				<nav class="header-nav header--v10-nav" role="navigation" aria-label="Main menu" id="header-nav">
88					<ul role="menu" aria-hidden="false" class="reset menu-level-1">
89	<li role="menuitem" aria-haspopup="true" class="is-category menu-457 has-drop ">
90		<button class="drop-control" role="button" aria-label="Toggle dropdown menu"></button>		<a aria-haspopup="true" aria-expanded="false" href="javascript:void(0);" title="Our World">Our World</a>
91<ul role="menu" aria-hidden="false" class="reset menu-level-2">
92	<li role="menuitem" aria-haspopup="true" class="is-page menu-32 ">
93				<a aria-haspopup="true" aria-expanded="false" href="/about-poa/our-story/" title="How We Got Here">How We Got Here</a>
94	</li>
95	<li role="menuitem" aria-haspopup="true" class="is-page menu-360 ">
96				<a aria-haspopup="true" aria-expanded="false" href="/about-poa/leadership-team/" title="At The Helm">At The Helm</a>
97	</li>
98	<li role="menuitem" aria-haspopup="true" class="is-page menu-64 ">
99				<a aria-haspopup="true" aria-expanded="false" href="/about-poa/why-poa/" title="The POA Difference">The POA Difference</a>
100	</li>
101	<li role="menuitem" aria-haspopup="true" class="is-page menu-356 ">
102				<a aria-haspopup="true" aria-expanded="false" href="/about-poa/why-billboards/" title="Impossible to Ignore">Impossible to Ignore</a>
103	</li>
104	<li role="menuitem" aria-haspopup="true" class="is-page menu-6 ">
105				<a aria-haspopup="true" aria-expanded="false" href="/about-poa/faq-s/" title="Got Questions?">Got Questions?</a>
106	</li>
107	<li role="menuitem" aria-haspopup="true" class="is-page menu-36 ">
108				<a aria-haspopup="true" aria-expanded="false" href="/about-poa/charity/" title=" Doing Good"> Doing Good</a>
109	</li>
110	<li role="menuitem" aria-haspopup="true" class="is-page menu-460 ">
111				<a aria-haspopup="true" aria-expanded="false" href="/about-poa/sustainability/" title="Building a Better Backyard">Building a Better Backyard</a>
112	</li>
113</ul>
114	</li>
115	<li role="menuitem" aria-haspopup="true" class="is-category menu-458 has-drop ">
116		<button class="drop-control" role="button" aria-label="Toggle dropdown menu"></button>		<a aria-haspopup="true" aria-expanded="false" href="javascript:void(0);" title="The Goods">The Goods</a>
117<ul role="menu" aria-hidden="false" class="reset menu-level-2">
118	<li role="menuitem" aria-haspopup="true" class="is-link menu-136 ">
119				<a aria-haspopup="true" aria-expanded="false" class="menu-136 Standard" href="https://billboards.poa.com.au/billboards.php" title="" >Locations</a>
120	</li>
121	<li role="menuitem" aria-haspopup="true" class="is-page menu-23 ">
122				<a aria-haspopup="true" aria-expanded="false" href="/billboards/digital-billboards/" title="Digital Billboards">Digital Billboards</a>
123	</li>
124	<li role="menuitem" aria-haspopup="true" class="is-page menu-29 ">
125				<a aria-haspopup="true" aria-expanded="false" href="/billboards/classic-highway-billboards/" title="Classic Highway Billboards">Classic Highway Billboards</a>
126	</li>
127	<li role="menuitem" aria-haspopup="true" class="is-page menu-30 ">
128				<a aria-haspopup="true" aria-expanded="false" href="/billboards/classic-inner-city-billboards/" title="Classic Inner City Billboards">Classic Inner City Billboards</a>
129	</li>
130	<li role="menuitem" aria-haspopup="true" class="is-page menu-31 ">
131				<a aria-haspopup="true" aria-expanded="false" href="/billboards/airport-billboards/" title="Airport Billboards">Airport Billboards</a>
132	</li>
133</ul>
134	</li>
135	<li role="menuitem" aria-haspopup="true" class="is-category menu-459 has-drop ">
136		<button class="drop-control" role="button" aria-label="Toggle dropdown menu"></button>		<a aria-haspopup="true" aria-expanded="false" href="javascript:void(0);" title="Extras">Extras</a>
137<ul role="menu" aria-hidden="false" class="reset menu-level-2">
138	<li role="menuitem" aria-haspopup="true" class="is-page menu-49 ">
139				<a aria-haspopup="true" aria-expanded="false" href="/the-extras/extensions/" title="Extensions">Extensions</a>
140	</li>
141	<li role="menuitem" aria-haspopup="true" class="is-page menu-60 ">
142				<a aria-haspopup="true" aria-expanded="false" href="/the-extras/billboard-design/" title="Billboard Design">Billboard Design</a>
143	</li>
144	<li role="menuitem" aria-haspopup="true" class="is-page menu-51 ">
145				<a aria-haspopup="true" aria-expanded="false" href="/the-extras/maintenance/" title="Maintenance">Maintenance</a>
146	</li>
147	<li role="menuitem" aria-haspopup="true" class="is-page menu-52 ">
148				<a aria-haspopup="true" aria-expanded="false" href="/the-extras/reflective/" title="Reflective">Reflective</a>
149	</li>
150	<li role="menuitem" aria-haspopup="true" class="is-page menu-53 ">
151				<a aria-haspopup="true" aria-expanded="false" href="/the-extras/skin-production/" title="Skin Production">Skin Production</a>
152	</li>
153	<li role="menuitem" aria-haspopup="true" class="is-page menu-275 ">
154				<a aria-haspopup="true" aria-expanded="false" href="/the-extras/signage/" title="Signage ">Signage </a>
155	</li>
156	<li role="menuitem" aria-haspopup="true" class="is-page menu-45 ">
157				<a aria-haspopup="true" aria-expanded="false" href="/the-extras/get-keep-attention/" title="Get & Keep Attention">Get &amp; Keep Attention</a>
158	</li>
159</ul>
160	</li>
161	<li role="menuitem" aria-haspopup="true" class="is-link menu-152 ">
162				<a aria-haspopup="true" aria-expanded="false" class="menu-152 Standard" href="https://billboards.poa.com.au/builder-1.php" title="" >Simulator</a>
163	</li>
164	<li role="menuitem" aria-haspopup="true" class="is-page menu-597 ">
165				<a aria-haspopup="true" aria-expanded="false" href="/our-crib/" title="Our Crib">Our Crib</a>
166	</li>
167	<li role="menuitem" aria-haspopup="true" class="is-page menu-599 ">
168				<a aria-haspopup="true" aria-expanded="false" href="/join-our-crew/" title="Join Our Crew">Join Our Crew</a>
169	</li>
170	<li role="menuitem" aria-haspopup="true" class="is-page menu-405 ">
171				<a aria-haspopup="true" aria-expanded="false" href="/landowners/" title="Got Land?">Got Land?</a>
172	</li>
173	<li role="menuitem" aria-haspopup="true" class="is-module menu-453 ">
174				<a aria-haspopup="true" aria-expanded="false" href="/news/" title="The Scoop">The Scoop</a>
175	</li>
176	<li role="menuitem" aria-haspopup="true" class="is-page menu-7 ">
177				<a aria-haspopup="true" aria-expanded="false" href="/contact/" title="Let's Chat">Let&#039;s Chat</a>
178	</li>
179</ul>
180				</div>
181			</div>
182		</div>
183		<button type="button" title="Menu Button" class="mm-menu-button header-v10__burger" aria-label="Open menu" aria-expanded="false">
184			<span></span>
185		</button>
186	</header>
187
188	<div id="page-content" class="page-content">
189<div class="section-hero">
190	
191	<div class="img">
192		<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/dba8997a-7757-4f49-9241-36117235c7d9/poafallback_1600.webp" srcset="https://cdn.xargocdn.com/poa-com-au/dba8997a-7757-4f49-9241-36117235c7d9/poafallback_400.webp 400w, https://cdn.xargocdn.com/poa-com-au/dba8997a-7757-4f49-9241-36117235c7d9/poafallback_800.webp 800w, https://cdn.xargocdn.com/poa-com-au/dba8997a-7757-4f49-9241-36117235c7d9/poafallback_1200.webp 1200w, https://cdn.xargocdn.com/poa-com-au/dba8997a-7757-4f49-9241-36117235c7d9/poafallback_1600.webp 1600w" sizes="100vw" alt="POA" />
193		
194		<span>Video Loading</span>
195		<iframe src="https://player.vimeo.com/video/1114748664?autopause=false&muted=1&autoplay=1&loop=1&background=1&app_id=122963" frameborder="0" allow="autoplay; fullscreen" title="POA" data-ready="true"></iframe>
196
197	</div>
198</div>
199
200
201<div class="section-why">
202	<div class="section-why-v2__bg" aria-hidden="true">
203		<img src="/templates/oracle/img/section-why-v2-bg.png?ver=" alt="" width="389" height="400" />
204	</div>
205	<div class="wrapper">
206		<div class="title waypoint">
207			<h2><span class="bold">No one reaches 96%&nbsp;<br /></span>of QLD like we do!*</h2>
208<p><span class="extracontent1"><span class="bold">With over 40 years of industry experience,</span> we can help you achieve your goals. Whether you&rsquo;re looking to capture the Southeast Queensland, the North Queensland market and everywhere in between, our expansive network of more than 2,000 billboards means we have the right piece of sky for you!</span></p>		</div>
209		
210		<div class="items odometer-items waypoint">
211			<div class="item" data-count="1">
212				<span class="item-title h2">
213					Cut Through 
214					
215					<br /><span>The Noise:</span>
216					
217				</span>
218					<span class="item-stat"><span class="odometer" data-odometer-format="(ddd)" data-odometer="5000">0</span><span class="item-stat-symbol">+</span></span>
219					
220					<span class="item-desc-title h8">Advertising messages are exposed to you on an average day</span>
221									
222				<p>So it&rsquo;s important you make a&nbsp;<strong>BIG IMPRESSION</strong>.</p>			</div>
223			<div class="item" data-count="2">
224				<span class="item-title h2">
225					Reach Your 
226					
227					<br /><span>Audience:</span>
228					
229				</span>
230				<p>You can reach more of your customers with billboard advertising.</p>		
231						<span class="item-stat"><span class="odometer" data-odometer-format="(ddd)" data-odometer="74">0</span><span class="item-stat-symbol">%</span></span>
232						
233						<span class="item-desc-title h8">of Australians see you daily!</span>
234						</div>
235			<div class="item" data-count="3">
236				<span class="item-title h2">
237					Repeat Exposure 
238					
239					<br /><span>Leads to action:</span>
240					
241				</span>
242				<p>In marketing, we say you need a minimum of 8 exposures before your customer will buy; how often do you drive past the same Billboards on your commute?</p>			
243						<span class="item-desc-title h8">Out-of-home-advertising can increase your online & in-store traffic by up to</span>
244								<span class="item-stat"><span class="odometer" data-odometer-format="(ddd)" data-odometer="63">0</span><span class="item-stat-symbol">%</span></span>
245						</div>
246		</div>
247	</div>
248</div>
249<div class="section-you">
250	<div class="wrapper">
251		<div class="title waypoint">
252			<h2>You <span>Everywhere</span></h2>
253		</div>
254		<div class="items">
255			<div class="item waypoint">
256				<a href="//www.poa.com.au/billboards/digital-billboards/" >
257					<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/b4b04c17-beec-46d9-a96f-87384c29d955/homeyou1_original.svg" alt="Digital" />
258					<span class="item-title h3">Digital</span>					
259				</a>
260			</div>
261			<div class="item waypoint">
262				<a href="//www.poa.com.au/billboards/classic-highway-billboards/" >
263					<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/105f0f1c-f83a-45f7-87eb-56b03833e4a7/homehighway_original.svg" alt="Highway" />
264					<span class="item-title h3">Highway</span>					
265				</a>
266			</div>
267			<div class="item waypoint">
268				<a href="//www.poa.com.au/billboards/classic-inner-city-billboards/" >
269					<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/fdfc5102-f75b-48fa-8267-4d8074795698/homeyou3_original.svg" alt="Inner City" />
270					<span class="item-title h3">Inner City</span>					
271				</a>
272			</div>
273			<div class="item waypoint">
274				<a href="//www.poa.com.au/billboards/airport-billboards/" >
275					<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/f0fa02ba-d704-4399-92ec-475c1769e129/homeairport_original.svg" alt="Airports" />
276					<span class="item-title h3">Airports</span>					
277				</a>
278			</div>
279		</div>
280	</div>
281</div>
282
283<div class="section-reviews">
284	<div class="wrapper">
285		<div class="title waypoint">
286			<h2><strong>The Proof</strong> is in the Pudding</h2>
287		</div>
288		<div class="feed waypoint">
289			
289<script nonce="WWpGbVlXTTBZVFUzWVdJNE16QXk=" src="https://elfsightcdn.com/platform.js" async></script>
289
290			<div class="elfsight-app-d3840127-7ef9-4855-9467-06674c9293b3" data-elfsight-app-lazy></div>
291		</div>
292	</div>
293</div>
294<div class="section-simulator waypoint">
295	<div class="swiper" data-swiper-type="home-simulator">
296		<div class="swiper-wrapper">
297			<div class="swiper-slide">
298				<div class="img">
299					<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/4da6ee57-3b14-4b4e-8525-013b4c9b2c0c/POA_ArtSimulatorHomepageImage1.crop_1920x699_0%2C290.preview_1600.webp" srcset="https://cdn.xargocdn.com/poa-com-au/4da6ee57-3b14-4b4e-8525-013b4c9b2c0c/POA_ArtSimulatorHomepageImage1.crop_1920x699_0%2C290.preview_400.webp 400w, https://cdn.xargocdn.com/poa-com-au/4da6ee57-3b14-4b4e-8525-013b4c9b2c0c/POA_ArtSimulatorHomepageImage1.crop_1920x699_0%2C290.preview_800.webp 800w, https://cdn.xargocdn.com/poa-com-au/4da6ee57-3b14-4b4e-8525-013b4c9b2c0c/POA_ArtSimulatorHomepageImage1.crop_1920x699_0%2C290.preview_1200.webp 1200w, https://cdn.xargocdn.com/poa-com-au/4da6ee57-3b14-4b4e-8525-013b4c9b2c0c/POA_ArtSimulatorHomepageImage1.crop_1920x699_0%2C290.preview_1600.webp 1600w" sizes="100vw" alt="Try our artwork simulator" />
300				</div>
301			</div>
302			<div class="swiper-slide">
303				<div class="img">
304					<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/0a881ad6-adbb-4be2-b5e6-b2f35d86bcde/POA_ArtSimulatorHomepageImage3.crop_1920x699_0%2C290.preview_1600.webp" srcset="https://cdn.xargocdn.com/poa-com-au/0a881ad6-adbb-4be2-b5e6-b2f35d86bcde/POA_ArtSimulatorHomepageImage3.crop_1920x699_0%2C290.preview_400.webp 400w, https://cdn.xargocdn.com/poa-com-au/0a881ad6-adbb-4be2-b5e6-b2f35d86bcde/POA_ArtSimulatorHomepageImage3.crop_1920x699_0%2C290.preview_800.webp 800w, https://cdn.xargocdn.com/poa-com-au/0a881ad6-adbb-4be2-b5e6-b2f35d86bcde/POA_ArtSimulatorHomepageImage3.crop_1920x699_0%2C290.preview_1200.webp 1200w, https://cdn.xargocdn.com/poa-com-au/0a881ad6-adbb-4be2-b5e6-b2f35d86bcde/POA_ArtSimulatorHomepageImage3.crop_1920x699_0%2C290.preview_1600.webp 1600w" sizes="100vw" alt="Try our artwork simulator" />
305				</div>
306			</div>
307			<div class="swiper-slide">
308				<div class="img">
309					<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/eea0e454-0217-4b92-889c-9c6ed734f3b2/POA_ArtSimulatorHomepageImage4.crop_1920x699_0%2C290.preview_1600.webp" srcset="https://cdn.xargocdn.com/poa-com-au/eea0e454-0217-4b92-889c-9c6ed734f3b2/POA_ArtSimulatorHomepageImage4.crop_1920x699_0%2C290.preview_400.webp 400w, https://cdn.xargocdn.com/poa-com-au/eea0e454-0217-4b92-889c-9c6ed734f3b2/POA_ArtSimulatorHomepageImage4.crop_1920x699_0%2C290.preview_800.webp 800w, https://cdn.xargocdn.com/poa-com-au/eea0e454-0217-4b92-889c-9c6ed734f3b2/POA_ArtSimulatorHomepageImage4.crop_1920x699_0%2C290.preview_1200.webp 1200w, https://cdn.xargocdn.com/poa-com-au/eea0e454-0217-4b92-889c-9c6ed734f3b2/POA_ArtSimulatorHomepageImage4.crop_1920x699_0%2C290.preview_1600.webp 1600w" sizes="100vw" alt="Try our artwork simulator" />
310				</div>
311			</div>
312			<div class="swiper-slide">
313				<div class="img">
314					<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/93db7bbf-01bb-49da-97a7-c58e883d6cd4/POA_ArtSimulatorHomepageImage5.crop_1920x699_0%2C290.preview_1600.webp" srcset="https://cdn.xargocdn.com/poa-com-au/93db7bbf-01bb-49da-97a7-c58e883d6cd4/POA_ArtSimulatorHomepageImage5.crop_1920x699_0%2C290.preview_400.webp 400w, https://cdn.xargocdn.com/poa-com-au/93db7bbf-01bb-49da-97a7-c58e883d6cd4/POA_ArtSimulatorHomepageImage5.crop_1920x699_0%2C290.preview_800.webp 800w, https://cdn.xargocdn.com/poa-com-au/93db7bbf-01bb-49da-97a7-c58e883d6cd4/POA_ArtSimulatorHomepageImage5.crop_1920x699_0%2C290.preview_1200.webp 1200w, https://cdn.xargocdn.com/poa-com-au/93db7bbf-01bb-49da-97a7-c58e883d6cd4/POA_ArtSimulatorHomepageImage5.crop_1920x699_0%2C290.preview_1600.webp 1600w" sizes="100vw" alt="Try our artwork simulator" />
315				</div>
316			</div>
317			<div class="swiper-slide">
318				<div class="img">
319					<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/904dab3b-5c6d-4adb-af52-708863f82e0d/POA_ArtSimulatorHomepageImage2.crop_1920x699_0%2C290.preview_1600.webp" srcset="https://cdn.xargocdn.com/poa-com-au/904dab3b-5c6d-4adb-af52-708863f82e
3190d/POA_ArtSimulatorHomepageImage2.crop_1920x699_0%2C290.preview_400.webp 400w, https://cdn.xargocdn.com/poa-com-au/904dab3b-5c6d-4adb-af52-708863f82e0d/POA_ArtSimulatorHomepageImage2.crop_1920x699_0%2C290.preview_800.webp 800w, https://cdn.xargocdn.com/poa-com-au/904dab3b-5c6d-4adb-af52-708863f82e0d/POA_ArtSimulatorHomepageImage2.crop_1920x699_0%2C290.preview_1200.webp 1200w, https://cdn.xargocdn.com/poa-com-au/904dab3b-5c6d-4adb-af52-708863f82e0d/POA_ArtSimulatorHomepageImage2.crop_1920x699_0%2C290.preview_1600.webp 1600w" sizes="100vw" alt="Try our artwork simulator" />
320				</div>
321			</div>
322		</div>
323	</div>
324	<div class="graphics">
325		<svg fill="none" height="520" viewBox="0 0 405 520" width="405" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="39123a" gradientUnits="userSpaceOnUse" x1="-117.338" x2="45.8622" y1="264.975" y2="70.1882"><stop offset=".1" stop-color="#004986"/><stop offset=".24" stop-color="#0065a4"/><stop offset=".45" stop-color="#009adb"/></linearGradient><linearGradient id="39123b" gradientUnits="userSpaceOnUse" x1="17.0462" x2="162.901" y1="179.107" y2="263.421"><stop offset=".19" stop-color="#c39200"/><stop offset=".23" stop-color="#ca9800"/><stop offset=".47" stop-color="#f0bd00"/><stop offset=".6" stop-color="#ffcb00"/></linearGradient><linearGradient id="39123c" gradientUnits="userSpaceOnUse" x1="-149.072" x2="54.4365" y1="-.354807" y2="73.8395"><stop offset=".35" stop-color="#ffcb00"/><stop offset=".49" stop-color="#e2b000"/><stop offset=".66" stop-color="#c39200"/></linearGradient><clipPath id="39123d"><path d="m-149-1h553.081v521h-553.081z"/></clipPath><g clip-path="url(#39123d)"><path d="m143.228-1c36.096 0 69.948 6.82862 101.61 20.4142 31.608 13.5676 59.285 32.1894 82.96 55.8118 23.675 23.6402 42.288 51.241 55.893 82.84 13.552 31.615 20.39 65.436 20.39 101.479s-6.838 69.845-20.39 101.479c-13.587 31.562-32.2 59.181-55.893 82.84-23.675 23.64-51.352 42.208-82.96 55.811-31.662 13.568-65.514 20.343-101.61 20.343-36.095 0-69.9651-6.775-101.6631-20.343-31.6621-13.603-59.3036-32.153-82.9245-55.811-23.7107-23.641-42.4315-51.278-56.2343-82.84-13.8391-31.652-20.7851-65.436-20.7851-101.479s6.946-69.864 20.7851-101.479c13.8028-31.581 32.5416-59.1998 56.2343-82.84 23.6209-23.6224 51.2624-42.2263 82.9245-55.8118 31.698-13.58558 65.5681-20.4142 101.6631-20.4142zm0 435.365c23.89 0 46.488-4.535 67.83-13.711 21.359-9.087 39.954-21.49 55.911-37.19 15.921-15.665 28.485-34.215 37.621-55.418 9.136-21.328 13.641-44.18 13.641-68.501 0-24.322-4.505-47.048-13.641-68.125-9.136-21.041-21.718-39.538-37.621-55.418-15.975-15.951-34.552-28.479-55.911-37.6197-21.36-9.1227-43.94-13.6572-67.83-13.6572s-47.2417 4.5345-68.5651 13.6572c-21.3235 9.1407-39.9725 21.6867-55.8933 37.6197-15.93871 15.898-28.48508 34.377-37.6211 55.418-9.154 21.077-13.7311 43.803-13.7311 68.125 0 24.321 4.5591 47.173 13.7311 68.501 9.13602 21.221 21.68239 39.753 37.6211 55.418 
32515.9029 15.7 34.5519 28.103 55.8933 37.19 21.3234 9.176 44.1901 13.711 68.5651 13.711z" fill="#000" opacity=".2"/><path d="m-32.403 264.653c-.0538-1.685-.1256-3.352-.1256-5.037 0-24.339 4.5411-47.047 13.713-68.106 9.15404-21.042 21.68247-39.52 37.6033-55.4 15.9028-15.934 34.5518-28.462 55.8573-37.6202 1.077-.4481 2.1539-.8603 3.2308-1.2904-5.1154-4.8392-10.7514-8.7105-16.9797-11.5961-12.0618-5.592-25.4518-8.6926-40.3495-9.4095-14.772-.6632-29.14917-.9858-43.0776-.9858h-18.6491s-.0897.0717-.1256.1255c-23.6927 23.6582-42.4135 51.2415-56.2163 82.8215-13.839 31.598-20.767 65.419-20.767 101.461 0 1.578.09 3.119.108 4.678l44.944.377h40.834z" fill="url(#39123a)"/><path d="m77.8934 97.1995c4.7745 4.5345 9.0822 9.9115 12.8874 16.1665 7.9156 12.976 11.8102 31.903 11.8102 56.905s-3.8946 43.911-11.8102 56.905c-7.8616 12.94-17.8054 22.225-29.8671 27.781-12.0618 5.538-25.6133 8.567-40.6546 9.015-15.0951.484-29.56203.681-43.4366.681h-9.2258c.5923 22.439 5.0616 43.588 13.5874 63.429 1.8128 4.194 3.7872 8.262 5.8693 12.241h19.6901c9.6745 0 20.5696-.376 32.5954-1.021 12.0797-.699 24.4646-2.563 37.2084-5.521 12.7258-3.082 25.2897-8.065 37.5497-14.947 12.295-6.972 23.208-16.686 32.649-29.197 9.477-12.528 17.141-28.479 22.921-47.925 5.851-19.411 8.723-43.23 8.723-71.459 0-28.228-2.872-52.191-8.723-71.8347-1.239-4.2298-2.603-8.2804-4.039-12.1876-7.341-.9141-14.808-1.4338-22.4-1.4338-23.172 0-44.9445 4.1402-65.3346 12.3668z" fill="url(#39123b)"/><path d="m78.809 6.95773c-.9872-.25093-1.9564-.57354-2.9436-.80653-12.7618-3.02897-25.2902-4.87503-37.5314-5.591941-12.2771-.6452233-23.0645-1.075372-32.32622-1.075372h-155.00778v75.706213h107.8198c23.585-23.5327 51.1906-42.1008 82.7809-55.6326 12.0797-5.1976 24.5004-9.3737 37.2263-12.59977z" fill="url(#39123c)"/><path d="m20.5644 76.1937c14.8976.7349 28.3056 3.8355 40.3493 9.4095 6.2284 2.8856 11.8823 6.7569 16.9798 11.5961 20.3901-8.2266 42.1805-12.3668 65.3345-12.3668 7.592 0 15.059.5198 22.4 1.4339-5.205-14.2129-11.613-26.275-19.259-36.0609-9.728-12.4922-20.695-22.2064-32.954-29.1425-11.362-6.4164-22.8854-11.0584-34.6061-14.08741-12.7258 3.20821-25.1286 7.40211-37.2262 12.59981-31.59033 13.5317-59.1959 32.0998-82.7809 55.6326h18.649c13.92843 0 28.3056.3226 43.0776.9857z" fill="#fff"/></g></svg>	</div>
326	<div class="text">
327		<img loading="lazy" src="/templates/oracle/img/try-our-artwork.svg" alt="Try our Artwork Simulator" />
328	</div>
329</div>
330
331<div class="section-everybody">
332    <div class="wrapper">
333        <div class="title waypoint">
334            <h2>Everybody's <span>Doing It</span></h2>
335        </div>
336        	<div class="home-logos-carousel waypoint">
337		<div class="swiper" data-swiper-type="home-logos">
338			<div class="swiper-wrapper">
339				<div class="swiper-slide">
340					<div class="item">
341						<div class="img">
342							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/a4142395-1cae-45c0-8b69-701615445a05/amazonlogo_original.webp" alt="Amazon" />
343						</div>
344					</div>
345				</div>
346				<div class="swiper-slide">
347					<div class="item">
348						<div class="img">
349							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/5f24dea4-3b92-49f1-baf3-dc9b06ce6566/applesm_original.webp" alt="Apple" />
350						</div>
351					</div>
352				</div>
353				<div class="swiper-slide">
354					<div class="item">
355						<div class="img">
356							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/db736ef4-f4e9-4e50-9224-9ad203813b9f/logoboq_original.webp" alt="BOQ" />
357						</div>
358					</div>
359				</div>
360				<div class="swiper-slide">
361					<div class="item">
362						<div class="img">
363							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/3cea6d15-4148-418f-8289-0947d93e04f4/cbalogo_original.webp" alt="CBA" />
364						</div>
365					</div>
366				</div>
367				<div class="swiper-slide">
368					<div class="item">
369						<div class="img">
370							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/12cdead9-ceaa-49bf-a747-416b28892fbf/cowboys_original.webp" alt="Cowboys" />
371						</div>
372					</div>
373				</div>
374				<div class="swiper-slide">
375					<div class="item">
376						<div class="img">
377							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/7a9b480f-52c3-4154-9f82-729b7d2e0da3/cqunilogo_400.webp" alt="CQ University" />
378						</div>
379					</div>
380				</div>
381				<div class="swiper-slide">
382					<div class="item">
383						<div class="img">
384							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/4a44a1a9-4702-4fa4-803a-be713d891e11/EbayWhiteLogo2_original.webp" alt="Ebay" />
385						</div>
386					</div>
387				</div>
388				<div class="swiper-slide">
389					<div class="item">
390						<div class="img">
391							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/c7a0a875-9c2e-4290-968e-3d193dae2843/ExplorePropertyWhiteLogo_400.webp" alt="Explore Property" />
392						</div>
393					</div>
394				</div>
395				<div class="swiper-slide">
396					<div class="item">
397						<div class="img">
398							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/885d7e91-7b62-410f-bebb-612c342f8edf/FordWhiteLogo_original.webp" alt="Ford" />
399						</div>
400					</div>
401				</div>
402				<div class="swiper-slide">
403					<div class="item">
404						<div class="img">
405							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/c0e53db4-b7f2-47a0-bffc-72253efe35ac/gglogo_original.webp" alt="Google" />
406						</div>
407					</div>
408				</div>
409				<div class="swiper-slide">
410					<div class="item">
411						<div class="img">
412							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/30dfb93b-7eca-45d2-88d3-6dfa2805097c/HarveyNormaWhiteLogo_400.webp" alt="Harvey Norman" />
413						</div>
414					</div>
415				</div>
416				<div class="swiper-slide">
417					<div class="item">
418						<div class="img">
419							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/3da34926-a432-4259-bf50-bf3339222b58/IkeaWhiteLogo2_original.webp" alt="Ikea" />
420						</div>
421					</div>
422				</div>
423				<div class="swiper-slide">
424					<div class="item">
425						<div class="img">
426							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/39942804-854f-4e49-869a-0c0ceb43c011/JamesCookWhiteLogo_400.webp" alt="James Cook" />
427						</div>
428					</div>
429				</div>
430				<div class="swiper-slide">
431					<div class="item">
432						<div class="img">
433							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/506615a4-49b8-4674-9d64-4ce176a7011c/KFCWhiteLogo_original.webp" alt="KFC" />
434						</div>
435					</div>
436				</div>
437				<div class="swiper-slide">
438					<div class="item">
439						<div class="img">
440							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/552840c8-83ea-419f-9d7f-b52bb8a2c7e7/mcdonalds_400.webp" alt="McDonalds" />
441						</div>
442					</div>
443				</div>
444				<div class="swiper-slide">
445					<div class="item">
446						<div class="img">
447							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/868f7c30-082c-42c1-9c55-3b4530ff17f9/NetflixWhiteLogo2_original.webp" alt="Netflix" />
448						</div>
449					</div>
450				</div>
451				<div class="swiper-slide">
452					<div class="item">
453						<div class="img">
454							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/ba0148f1-a5d9-493f-9a0c-370828905a9c/OptusWhiteLogo_original.webp" alt="Optus" />
455						</div>
456					</div>
457				</div>
458				<div class="swiper-slide">
459					<div class="item">
460						<div class="img">
461							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/42b5cec9-ba27-4046-a19b-e6d93348e09e/PBRWhiteLogo_original.webp" alt="PBR" />
462						</div>
463					</div>
464				</div>
465				<div class="swiper-slide">
466					<div class="item">
467						<div class="img">
468							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/b2e366f5-b8df-46e3-9140-09ab8b454568/qldgovlogo_original.webp" alt="QLD Gov" />
469						</div>
470					</div>
471				</div>
472				<div class="swiper-slide">
473					<div class="item">
474						<div class="img">
475							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/a82f548e-9a54-409a-a179-526d4b40191f/StanWhiteLogo2_original.webp" alt="Stan" />
476						</div>
477					</div>
478				</div>
479				<div class="swiper-slide">
480					<div class="item">
481						<div class="img">
482							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/04c2bc2a-6a10-46bd-9653-2e88bb87f7f8/TikTokWhiteLogo_original.webp" alt="TikTok" />
483						</div>
484					</div>
485				</div>
486				<div class="swiper-slide">
487					<div class="item">
488						<div class="img">
489							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/3f0206be-9a2d-4b3f-b645-5050e18857a4/cityoftsv_original.webp" alt="TownsvilleCouncil" />
490						</div>
491					</div>
492				</div>
493				<div class="swiper-slide">
494					<div class="item">
495						<div class="img">
496							<img loading="lazy" src="https://cdn.xargocdn.com/poa-com-au/82e5c267-fb31-4f3f-a710-5616a5452e09/ToyotaWhiteLogo_original.webp" alt="Toyota" />
497						</div>
498					</div>
499				</div>
500			
501			</div>
502		</div>
503	</div>
504        <div class="feed waypoint">
505            
505<script nonce="WWpGbVlXTTBZVFUzWVdJNE16QXk=" src="https://elfsightcdn.com/platform.js" async></script>
505
506            <div class="elfsight-app-285c5af7-9160-44eb-8e81-59cb20b93543" data-elfsight-app-lazy></div>
507        </div>
508    </div>
509</div>
510
511<div class="section-faqs">
512	<div class="wrapper">
513		<div class="title">
514			<h2>Frequently Asked <span>Questions</span></h2>
515			<a href="#footer-form" class="link2">Let's Talk</a>
516		</div>
517		<div class="text">
518<accordion-holder id="acc-home-faqs" class="hide-on-load"> 
519    <div class="accordion">
520        <accordion-item 
521            data-itemid="367" 
522            identifier="acc-home-faqs" 
523            headline="* How does POA reach 96% of Queensland?"
524            link=""
525            src=""
526            srcset=""
527            target="_self"
528            >
529            <p><span>POA has over 2000 outdoor advertising opportunities throughout Queensland with majority being in regional areas, and more than half of Queensland&rsquo;s population lives regionally. </span><span>Source: OMA Move* over a 12-month period.</span></p>        </accordion-item>
530        <accordion-item 
531            data-itemid="347" 
532            identifier="acc-home-faqs" 
533            headline="What’s The Difference Between Static and Digital Billboards? "
534            link=""
535            src=""
536            srcset=""
537            target="_self"
538            >
539            <p>Static billboards are the traditional option where the artwork is physically installed and displayed. There&rsquo;s a lot of room for creativity with static billboards - we can create billboard extensions to achieve a pop-out or 3D effect, add reflective material to increase visibility, and use moving components to bring the artwork to life.</p>
540<p>Digital billboards display a rotation of visuals in high definition, running continuously to reach a wider audience. Our digital billboard advertising has a quick turnaround from booking to going live, and unlimited artwork changes at any time during the campaign. Terms and conditions apply.</p>        </accordion-item>
541        <accordion-item 
542            data-itemid="348" 
543            identifier="acc-home-faqs" 
544            headline="How Soon Can a Billboard Campaign Go Live After Booking? "
545            link=""
546            src=""
547            srcset=""
548            target="_self"
549            >
550            <p>Our digital billboards can go live within a week of booking.</p>
551<p>Our static billboards require 6 weeks for in-house development of the artwork, production of the skin, and on-site installation. This can be reduced to 3 weeks if the artwork is complete and ready.</p>        </accordion-item>
552        <accordion-item 
553            data-itemid="349" 
554            identifier="acc-home-faqs" 
555            headline="How Often Will My Media Be Shown on Digital Billboards? "
556            link=""
557            src=""
558            srcset=""
559            target="_self"
560            >
561            <p>POA&rsquo;s digital billboards have a standard 10-second display time. We also offer 20 and 25-second display times. Digital billboards in airports and terminals have different display times between 7-15 seconds.</p>        </accordion-item>
562        <accordion-item 
563            data-itemid="350" 
564            identifier="acc-home-faqs" 
565            headline="How Often Can I Change the Billboard Artwork? "
566            link=""
567            src=""
568            srcset=""
569            target="_self"
570            >
571            <p>The artwork for a digital billboard can be changed hourly, daily, or weekly, with no limit on the number of changes. Use our online artwork simulator to preview how your media will look on the digital billboard.</p>
572<p>Artwork for static billboards has a longer turnaround time - most clients refresh the artwork every 6-12 months.</p>        </accordion-item>
573        <accordion-item 
574            data-itemid="351" 
575            identifier="acc-home-faqs" 
576            headline="Can Digital Billboards Display Animated Visuals? "
577            link=""
578            src=""
579            srcset=""
580            target="_self"
581            >
582            <p>Our digital billboards in airports and terminals can display animated visuals. Animated visuals for roadside digital billboards are not permitted.</p>        </accordion-item>
583        <accordion-item 
584            data-itemid="352" 
585            identifier="acc-home-faqs" 
586            headline="How Long Do I Need to Book the Billboards for? "
587            link=""
588            src=""
589            srcset=""
590            target="_self"
591            >
592            <p>There is no minimum or maximum duration for booking billboard advertising. Static billboards are booked in 4-week blocks and most advertisements are booked for one to three years. Digital billboards can be booked in weekly intervals as no physical installation is required.</p>        </accordion-item>
593        <accordion-item 
594            data-itemid="353" 
595            identifier="acc-home-faqs" 
596            headline="Can You Help Design the Billboard Artwork?"
597            link=""
598            src=""
599            srcset=""
600            target="_self"
601            >
602            <p>Yes. POA has an in-house team of graphic designers who can work with you to create visually stunning billboard media that resonates with your audience. We also work with award-winning copywriters to craft memorable messaging that aligns with your brand. The Queensland Multi Media Awards have awarded our billboard designs for creativity and a high standard of quality.</p>        </accordion-item>
603        <accordion-item 
604            data-itemid="354" 
605            identifier="acc-home-faqs" 
606            headline="How Often Will the Billboard Be Maintained? "
607            link=""
608            src=""
609            srcset=""
610            target="_self"
611            >
612            <p>Our static billboards are inspected twice a year to ensure high visibility and quality. We monitor our billboards and arrange professional cleaning to remove dirt and mildew from the canvas. We also mow and maintain the grass and other vegetation around the sign structures to ensure full visibility.</p>        </accordion-item>
613        <accordion-item 
614            data-itemid="355" 
615            identifier="acc-home-faqs" 
616            headline="How Is the Performance of the Digital Billboards Measured? "
617            link=""
618            src=""
619            srcset=""
620            target="_self"
621            >
622            <p>We use Broadsign for digital scheduling, to provide proof of play and performance reports. We are planning to deliver more performance metrics in the near future.</p>
623<p>Businesses can track the performance of billboards by benchmarking the traffic of their website (or other target destination, like a specific store branch) at the start of the campaign. As the billboard campaign goe
623s on, businesses can attribute the increase in traffic, revenue, or online searches to billboard advertising, providing a real-time view of performance.</p>
624<p>There are also less measurable benefits, such as brand recognition and perception, that still have a tangible impact on the business.</p>        </accordion-item>
625    </div>
626</accordion-holder>
627		</div>
628	</div>
629</div>
630
631
632
633		<footer class="contrast-inverted footer--v2" role="contentinfo">
634			<div class="footer-v2__bg" aria-hidden="true"></div>
635			<div class="wrapper">
636				<div class="footer-info">
637					<span class="item-title h2">Find <span>Us</span></span>
638					<a class="item-phone h2" href="tel:0747584600">07 4758 4600</a>
639					<div class="item-addresses">
640					<p>221 Sturt Street<br /> Townsville, QLD 4810</p>
641<p>PO BOX 1754, TOWNSVILLE, QLD 4810</p>					</div>
642					<div class="footer-copyright footer-copyright--lg">
643						<p>
644							&copy; 2026 POA
645							<span>|</span> <a href="/sitemap/">Sitemap</a>
646							<span>|</span> <a href="/privacy-policy/">Privacy Policy</a>
647						</p>
648						<p>Site by <a aria-label="OracleStudio" target="_blank" rel="noopener noreferrer" href="https://www.oraclestudio.com.au">OracleStudio</a> <span>|</span>
649							Design by <a aria-label="Novellus" target="_blank" rel="noopener noreferrer" href="javascript:;">Novellus</a></p>
650					</div>
651				</div>
652				<div class="footer-social">
653					<span class="item-title h2">Let's Get <br /><span>Social</span></span>
654					<ul class="reset">
655											<li>
656						<a rel="nofollow noopener noreferrer" target="_blank" href="https://www.facebook.com/POABillboards/" aria-label="Facebook">
657							<svg fill="none" height="19" viewBox="0 0 10 19" width="10" xmlns="http://www.w3.org/2000/svg"><path d="m9.18359 10.375h-2.63671v7.875h-3.51563v-7.875h-2.882812v-3.23438h2.882812v-2.49609c0-2.8125 1.6875-4.39453 4.25391-4.39453 1.23046 0 2.53125.246094 2.53125.246094v2.777346h-1.44141c-1.40625 0-1.82812.84375-1.82812 1.75781v2.10937h3.1289z" fill="#001d3c"/></svg>							<span>Facebook</span>
658						</a>
659					</li>
660					<li>
661						<a rel="nofollow noopener noreferrer" target="_blank" href="https://www.instagram.com/poa_billboards/" aria-label="Instagram">
662							<svg fill="none" height="17" viewBox="0 0 16 17" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 4.20703c2.2148 0 4.043 1.82813 4.043 4.04297 0 2.25-1.8282 4.043-4.043 4.043-2.25 0-4.04297-1.793-4.04297-4.043 0-2.21484 1.79297-4.04297 4.04297-4.04297zm0 6.67967c1.44141 0 2.6016-1.16014 2.6016-2.6367 0-1.44141-1.16019-2.60156-2.6016-2.60156-1.47656 0-2.63672 1.16015-2.63672 2.60156 0 1.47656 1.19531 2.6367 2.63672 2.6367zm5.1328-6.82029c0-.52735-.4219-.94922-.9492-.94922-.5274 0-.9492.42187-.9492.94922 0 .52734.4218.94921.9492.94921.5273 0 .9492-.42187.9492-.94921zm2.6719.94921c.0703 1.30079.0703 5.20318 0 6.50388-.0703 1.2657-.3516 2.3555-1.2656 3.3047-.9141.9141-2.0391 1.1953-3.3047 1.2656-1.30081.0704-5.20315.0704-6.50393 0-1.26563-.0703-2.35547-.3515-3.30469-1.2656-.914061-.9492-1.195311-2.039-1.265624-3.3047-.0703122-1.3007-.0703122-5.20309 0-6.50388.070313-1.26562.351563-2.39062 1.265624-3.30468.94922-.914065 2.03906-1.195315 3.30469-1.265628 1.30078-.070312 5.20312-.070312 6.50393 0 1.2656.070313 2.3906.351563 3.3047 1.265628.914.91406 1.1953 2.03906 1.2656 3.30468zm-1.6875 7.87498c.4219-1.0195.3164-3.48044.3164-4.6406 0-1.125.1055-3.58594-.3164-4.64062-.2813-.66797-.8086-1.23047-1.4766-1.47657-1.0547-.42187-3.5156-.3164-4.6406-.3164-1.16016 0-3.62109-.10547-4.64062.3164-.70313.28125-1.23047.8086-1.51172 1.47657-.42188 1.05468-.31641 3.51562-.31641 4.64062 0 1.16016-.10547 3.6211.31641 4.6406.28125.7032.80859 1.2305 1.51172 1.5117 1.01953.4219 3.48046.3165 4.64062.3165 1.125 0 3.5859.1054 4.6406-.3165.668-.2812 1.2305-.8085 1.4766-1.5117z" fill="#001d3c"/></svg>							<span>Instagram</span>
663						</a>
664					</li>
665					<li>
666						<a rel="nofollow noopener noreferrer" target="_blank" href="https://www.linkedin.com/company/poabillboards" aria-label="LinkedIn">
667							<svg width="15" height="14" viewBox="0 0 15 14" fill="none" xmlns="http://www.w3.org/2000/svg">
668<path fill-rule="evenodd" clip-rule="evenodd" d="M0.182196 13.655H3.25363V4.4415H0.182196V13.655ZM1.71748 3.18394C2.78821 3.18394 3.45568 2.47554 3.45568 1.59154C3.43582 0.687744 2.78821 0 1.73734 0C0.686474 0 0 0.686884 0 1.59068C0 2.47554 0.666614 3.18308 1.69848 3.18308H1.71748V3.18394ZM14.3322 13.655V8.37258C14.3322 5.54241 12.8168 4.22545 10.7953 4.22545C9.16421 4.22545 8.4337 5.11978 8.02699 5.74727V4.4415H4.9547C4.99528 5.30656 4.9547 13.655 4.9547 13.655H8.02699V8.50944C8.02699 8.23486 8.04685 7.95942 8.12802 7.76316C8.34994 7.21314 8.85508 6.64332 9.70389 6.64332C10.8161 6.64332 11.2608 7.48772 11.2608 8.72635V13.6559L14.3322 13.655Z" fill="#003B4A"/>
669</svg>
670							<span>LinkedIn</span>
671						</a>
672					</li>
673					</ul>
674				</div>
675				<div class="footer-form" id="footer-form">
676					<span class="item-title h2">Let's <span>Talk Now</span></span>
677					<link href="https://assets.xargocdn.com/surveyjs/v2/survey-core.min.css" type="text/css" rel="stylesheet">
678<link href="/templates/oracle/css/surveyjs-min.css?ver=1404" type="text/css" rel="stylesheet">
679<script type="text/javascript" src="https://assets.xargocdn.com/surveyjs/v2/survey.core.min.js"></script>
vendor: 1 bytes, line 679
679
680<script type="text/javascript" src="https://assets.xargocdn.com/surveyjs/v2/survey-js-ui.min.js"></script>
vendor: 1 bytes, line 680
680
681<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" defer></script>
vendor: 1 bytes, line 681
681
682<script>
683(function() {
684    if (window.SurveyJsTurnstile) return;
685
686    window.SurveyJsTurnstile = {
687        tokens: {},
688
689        setToken: function(formId, token) {
690            this.tokens[formId] = token || '';
691        },
692
693        getToken: function(formId) {
694            return this.tokens[formId] || '';
695        },
696
697        clearToken: function(formId) {
698            this.tokens[formId] = '';
699        },
700
701        readTokenFromDom: function(formId) {
702            var input = document.querySelector(
703                '#turnstile-container-' + formId + ' input[name="cf-turnstile-response"]'
704            );
705            return (input && input.value) ? input.value : '';
706        },
707
708        getTokenForSubmit: function(formId) {
709            var token = this.getToken(formId);
710            if (!token) token = this.readTokenFromDom(formId);
711            if (token) this.setToken(formId, token);
712            return token;
713        },
714
715        isContainerVisible: function(formId) {
716            var container = document.querySelector('#turnstile-container-' + formId);
717            if (!container) return false;
718
719            // Open Fancybox modals are visible even before Turnstile renders (empty container = 0 height).
720            if (container.closest('.fancybox__container:not([aria-hidden="true"])')) {
721                return true;
722            }
723
724            var el = container;
725            while (el) {
726                var style = window.getComputedStyle(el);
727                if (style.display === 'none' || style.visibility === 'hidden') {
728                    return false;
729                }
730                el = el.parentElement;
731            }
732
733            return container.offsetParent !== null;
734        },
735
736        hasLiveWidget: function(formId) {
737            var container = document.querySelector('#turnstile-container-' + formId);
738            return !!(container && container.querySelector('iframe[src*="challenges.cloudflare.com"]'));
739        },
740
741        getSurveyModel: function(formId) {
742            return window['survey' + formId] || null;
743        },
744
745        rerenderWidget: function(formId, survey) {
746            if (typeof turnstile === 'undefined') return;
747            survey = survey || this.getSurveyModel(formId);
748            var container = document.querySelector('#turnstile-container-' + formId);
749            if (!container) return;
750            var turnstileElement = container.querySelector('.cf-turnstile-surveyjs');
751            if (!turnstileElement) return;
752
753            this.clearToken(formId);
754            this.clearError(formId);
755
756            container.querySelectorAll('iframe').forEach(function(iframe) {
757                iframe.remove();
758            });
759            turnstileElement.innerHTML = '';
760
761            var self = this;
762            turnstile.render(turnstileElement, {
763                sitekey: turnstileElement.getAttribute('data-sitekey'),
764                appearance: turnstileElement.getAttribute('data-appearance') || 'always',
765                theme: turnstileElement.getAttribute('data-theme') || 'light',
766                callback: function(token) {
767                    self.setToken(formId, token);
768                    self.clearError(formId);
769                    if (survey) self.syncCompleteButton(survey, formId);
770                },
771                'expired-callback': function() {
772                    self.clearToken(formId);
773                    if (survey) self.syncCompleteButton(survey, formId);
774                },
775                'error-callback': function() {
776                    self.clearToken(formId);
777                    if (survey) self.syncCompleteButton(survey, formId);
778                }
779            });
780
781            if (survey) this.syncCompleteButton(survey, formId);
782        },
783
784        refreshVisibleWidgets: function(rootEl) {
785            rootEl = rootEl || document;
786            var self = this;
787            rootEl.querySelectorAll('[id^="turnstile-container-"]').forEach(function(container) {
788                var formId = container.getAttribute('data-form-id') ||
789                    container.id.replace('turnstile-container-', '');
790                if (!formId || !self.isContainerVisible(formId)) return;
791
792                var survey = self.getSurveyModel(formId);
793                var hasToken = !!self.getTokenForSubmit(formId);
794                if (!self.hasLiveWidget(formId) || !hasToken) {
795                    self.rerenderWidget(formId, survey);
796                } else if (survey) {
797                    self.syncCompleteButton(survey, formId);
798                }
799            });
800        },
801
802        resetWidget: function(formId) {
803            if (typeof turnstile === 'undefined') return;
804            this.clearToken(formId);
805            var survey = this.getSurveyModel(formId);
806            if (this.hasLiveWidget(formId)) {
807                var el = document.querySelector('#turnstile-container-' + formId + ' .cf-turnstile-surveyjs');
808                try {
809                    if (el) turnstile.reset(el);
810                } catch (e) {
811                    this.rerenderWidget(formId, survey);
812                }
813            } else {
814                this.rerenderWidget(formId, survey);
815            }
816            if (survey) this.syncCompleteButton(survey, formId);
817        },
818
819        syncCompleteButton: function(survey, formId) {
820            var hasToken = !!this.getTokenForSubmit(formId);
821            var surveyContainer = document.getElementById('surveyContainer-' + formId);
822            if (!surveyContainer) return;
823            var btn = surveyContainer.querySelector('.sd-navigation__complete-btn') ||
824                surveyContainer.querySelector('.sd-navigation .sd-btn--action');
825            if (!btn) return;
826            var shouldDisable = survey.isLastPage && !hasToken;
827            btn.disabled = shouldDisable;
828            btn.setAttribute('aria-disabled', shouldDisable ? 'true' : 'false');
829            btn.classList.toggle('turnstile-complete--waiting', shouldDisable);
830        },
831
832        showError: function(formId, message) {
833            var container = document.querySelector('#turnstile-container-' + formId);
834            if (!container) return;
835            var msg = container.querySelector('.turnstile-error-msg');
836            if (!msg) {
837                msg = document.createElement('p');
838                msg.className = 'turnstile-error-msg';
839                msg.setAttribute('role', 'alert');
840                msg.style.color = '#b21f03';
841                msg.style.marginTop = '0.75em';
842                container.appendChild(msg);
843            }
844            msg.textContent = message;
845            container.scrollIntoView({ behavior: 'smooth', block: 'center' });
846        },
847
848        clearError: function(formId) {
849            var msg = document.querySelector('#turnstile-container-' + formId + ' .turnstile-error-msg');
850            if (msg) msg.remove();
851        }
852    };
853
854    function refreshSurveyTurnstileInFancybox(attempt) {
855        attempt = attempt || 0;
856        if (typeof turnstile === 'undefined') {
857            if (attempt < 20) {
858                setTimeout(function() {
859                    refreshSurveyTurnstileInFancybox(attempt + 1);
860                }, 100);
861            }
862            return;
863        }
864        if (!window.SurveyJsTurnstile) return;
865        var fancybox = document.querySelector('.fancybox__container:not([aria-hidden="true"])');
866        if (!fancybox) return;
867        requestAnimationFrame(function() {
868            requestAnimationFrame(function() {
869                SurveyJsTurnstile.refreshVisibleWidgets(fancybox);
870            });
871        });
872    }
873
874    if (!window.__surveyjsFancyboxHooked) {
875        window.__surveyjsFancyboxHooked = true;
876
877        document.addEventListener('click', function(event) {
878            if (!event.target.closest('[data-fancybox]')) return;
879            setTimeout(refreshSurveyTurnstileInFancybox, 50);
880        });
881
882        document.addEventListener('fancybox:reveal', refreshSurveyTurnstileInFancybox);
883    }
884})();
885</script>
885
886<style>
887
888.success-overlay-17, #success-overlay-17 {
889    display: none !important;
890    opacity: 0 !important;
891    visibility: hidden !important;
892    pointer-events: none !important;
893}
894
895</style>
896<div id="form-17" class="surveyjs-holder" data-load="surveyjs" data-load-css data-load-js data-load-type="force">
897    <input id="formid-17" type="hidden" value="17" name="formid" />
898    <input id="pageurl" class="form-page-url" type="hidden" value="/" name="pageurl" />
899    <input id="paymentElements-17" type="hidden" value="" name="paymentElements" />
900	<div class="surveyjs-form-shell">
901	<h3 class="form-title">Get In Touch</h3>
902    <div id="surveyContainer-17"></div>
903	</div>
904<script>
905
906Survey.surveyLocalization.getLocaleStrings("en").filePlaceholder =
907    "Drag and drop a file here or click the button below to select a file to upload.";
908
909
910
911
912    var surveyJSON17 = {"pages":[{"name":"page1","elements":[{"type":"text","name":"question1","title":"First Name","isRequired":true,"placeholder":"First Name"},{"type":"text","name":"question2","startWithNewLine":false,"title":"Surname","isRequired":true,"placeholder":"Surname"},{"type":"text","name":"question3","title":"Company","isRequired":true,"placeholder":"Company"},{"type":"text","name":"question4","startWithNewLine":false,"title":"Job Title","isRequired":true,"placeholder":"Job Title"},{"type":"text","name":"question5","title":"Area Based","isRequired":true,"placeholder":"Area Based"},{"type":"dropdown","name":"question6","title":"What region are you interested in?","choices":[{"value":"item1","text":"Airlie Beach"},{"value":"item2","text":"Augathella"},{"value":"item3","text":"Biloela"},{"value":"item4","text":"Brisbane"},{"value":"item5","text":"Bowen"},{"value":"item6","text":"Cairns"},{"value":"item7","text":"Charters Towers"},{"value":"item8","text":"Chinchilla"},{"value":"item9","text":"Clermont"},{"value":"item10","text":"Dalby"},{"value":"item11","text":"Emerald"},{"value":"item12","text":"Giru"},{"value":"item13","text":"Gladstone"},{"value":"item14","text":"Goondiwindi"},{"value":"item15","text":"Hervey Bay"},{"value":"item16","text":"Hughenden"},{"value":"item17","text":"Hinchinbrook"},{"value":"item18","text":"Innisfail"},{"value":"item19","text":"Julia Creek"},{"value":"item20","text":"Mackay"},{"value":"item21","text":"Maryborough"},{"value":"item22","text":"Miles"},{"value":"item23","text":"Milaa Milaa"},{"value":"item24","text":"Mount Isa"},{"value":"item25","text":"Port Douglas"},{"value":"item26","text":"Richmond"},{"value":"item27","text":"Rockhampton"},{"value":"item28","text":"St George"},{"value":"item29","text":"Tablelands"},{"value":"item30","text":"Toowoomba"},{"value":"item31","text":"Townsville"},{"value":"item32","text":"Tully"},{"value":"item33","text":"Winton"}],"placeholder":"What region are you interested in?"},{"type":"text","name":"question7","title":"Phone Number","isRequired":true,"placeholder":"Phone Number"},{"type":"text","name":"question8","startWithNewLine":false,"title":"Email Address","isRequired":true,"inputType":"email","placeholder":"Email Address"}]},{"name":"page2","elements":[{"type":"comment","name":"question9","title":"Your Message","placeholder":"Your Message"},{"type":"html","name":"turnstile-widget","title":"Security check","html":"<div id='turnstile-container-17' data-form-id='17'><div class='cf-turnstile-surveyjs' data-appearance='interaction-only' data-sitekey='0x4AAAAAAAfn5Ry99YNSWl_B' data-theme='light'><\/div><\/div>"}]}],"completeText":"Send"};
913    var survey17 = new Survey.Model(surveyJSON17);
914
915    // Signature pad: pen color (canvas API does not support CSS variables) and optional dimensions
916    (function() {
917        var survey = survey17;
918        var root = document.documentElement;
919        var resolved = getComputedStyle(root).getPropertyValue('--colorSecondary').trim();
920        var sigWidth = 1400;
921        var sigHeight = 300;
922        survey.getAllQuestions().forEach(function(q) {
923            if (q.getType() === 'signaturepad') {
924                if (resolved) q.penColor = resolved;
925                if (sigWidth != null && sigWidth > 0) q.signatureWidth = sigWidth;
926                if (sigHeight != null && sigHeight > 0) q.signatureHeight = sigHeight;
927            }
928        });
929    })();
930
931    (function() {
932    var turnstileFormId = '17';
933    var surveyTurnstile = survey17;
934    var SJT = window.SurveyJsTurnstile;
935
936    survey17.onAfterRenderQuestion.add(function (survey, options) {
937        if (options.question.name === "turnstile-widget") {
938            const formId = turnstileFormId;
939            const hasWidget = SJT.hasLiveWidget(formId);
940            const hasToken = !!SJT.getTokenForSubmit(formId);
941
942            // Only render while visible; hidden modals refresh on Fancybox reveal.
943            if (SJT.isContainerVisible(formId) && (!hasWidget || !hasToken)) {
944                SJT.rerenderWidget(formId, surveyTurnstile);
945            } else {
946                SJT.syncCompleteButton(surveyTurnstile, formId);
947            }
948        } else if (options.question.getType() === "dropdown") {
949            // Replace SurveyJS custom dropdown with native <select> (e.g. for Fancybox compatibility)
950            const question = options.question;
951            const root = options.htmlElement;
952            if (root.querySelector("select.sd-dropdown-native")) return;
953
954            const choices = question.visibleChoices || question.choices || [];
955            const valueKey = question.valuePropertyName || "value";
956            const textKey = question.textPropertyName || "text";
957
958            const select = document.createElement("select");
959            select.setAttribute("aria-label", question.title);
960            select.className = "sd-input sd-dropdown sd-dropdown-native";
961
962            if ( question.jsonObj.class && question.jsonObj.class === "is-payment-dropdown") {
963                select.classList.add("is-payment-dropdown");
964            }
965
966            select.id = question.inputId;
967            if (question.isRequired) select.required = true;
968            if (question.readOnly) select.disabled = true;
969
970            const placeholder = question.placeholder || question.optionsCaption || "Select...";
971            const emptyOption = document.createElement("option");
972            emptyOption.value = "";
973            emptyOption.textContent = placeholder;
974            select.appendChild(emptyOption);
975
976            choices.forEach(function(choice) {
977                const opt = document.createElement("option");
978                opt.value = choice[valueKey] !== undefined ? String(choice[valueKey]) : (choice.value !== undefined ? String(choice.value) : "");
979                opt.textContent = choice[textKey] !== undefined ? choice[textKey] : (choice.text !== undefined ? choice.text : opt.value);
980                if (String(question.value) === opt.value) opt.selected = true;
981                select.appendChild(opt);
982            });
983
984            select.addEventListener("change", function() {
985                question.value = this.value === "" ? undefined : this.value;
986            });
987
988            const wrap = document.createElement("div");
989            wrap.className = "sd-dropdown-native-wrapper";
990            wrap.appendChild(select);
991
992            const wrapper = root.querySelector(".sv-dropdown_select-wrapper") || root.querySelector(".sd-dropdown");
993            if (wrapper) {
994                wrapper.replaceWith(wrap);
995            } else {
996                const content = root.querySelector(".sd-question__content") || root.querySelector(".sd-input");
997                if (content) {
998                    content.replaceWith(wrap);
999                } else {
1000                    root.appendChild(wrap);
1001                }
1002            }
1003        }
1004    });
1005
1006
1007    survey17.applyTheme({
1008        "themeName": "defaultV2",
1009        "isPanelless": true
1010    });
1011    survey17.questionErrorLocation = "bottom";
1012
1013    (function scrollSurveyToTopOnStepChange() {
1014        var surveyModel = survey17;
1015        var formEl = document.getElementById('form-17');
1016
1017        var scrollAboveFormPx = 100;
1018
1019        function scrollToFormTop() {
1020            if (formEl) {
1021                var rect = formEl.getBoundingClientRect();
1022                var docY = window.pageYOffset || document.documentElement.scrollTop || 0;
1023                var y = rect.top + docY - scrollAboveFormPx;
1024                window.scrollTo({ top: Math.max(0, y), left: 0, behavior: 'auto' });
1025            } else {
1026                window.scrollTo({ top: 0, left: 0, behavior: 'auto' });
1027            }
1028        }
1029
1030        function scrollAfterLayout() {
1031            window.requestAnimationFrame(function () {
1032                window.requestAnimationFrame(scrollToFormTop);
1033            });
1034        }
1035
1036        surveyModel.onCurrentPageChanged.add(function () {
1037            scrollAfterLayout();
1038            SJT.syncCompleteButton(surveyModel, turnstileFormId);
1039            if (surveyModel.isLastPage && SJT.isContainerVisible(turnstileFormId)) {
1040                SJT.refreshVisibleWidgets(document.getElementById('form-' + turnstileFormId));
1041            }
1042        });
1043
1044        if (surveyModel.onShowingPreview && typeof surveyModel.onShowingPreview.add === 'function') {
1045            surveyModel.onShowingPreview.add(function () {
1046                scrollAfterLayout();
1047            });
1048        }
1049    })();
1050
1051    
1052
1053
1054
1055
1056// // Render the Survey
1057// document.addEventListener("DOMContentLoaded", function () {
1058//     $("#surveyContainer").Survey({ model: survey9 });
1059// });
1060
1061
1062
1063
1064
1065/**
1066 * IMPORTANT: SurveyJS stores sender.data as a plain JS object.
1067 * Object keys are inserted in the order the user answers questions.
1068 * This function rebuilds a new object in the SURVEY DEFINITION ORDER.
1069 */
1070function reorderObjectByKeys(obj, orderedKeys) {
1071    if (!obj || typeof obj !== "object" || Array.isArray(obj)) return obj;
1072
1073    const out = {};
1074    // first: known keys in desired order
1075    orderedKeys.forEach(k => {
1076        if (Object.prototype.hasOwnProperty.call(obj, k)) out[k] = obj[k];
1077    });
1078    // then: any remaining keys (don't lose anything)
1079    Object.keys(obj).forEach(k => {
1080        if (!Object.prototype.hasOwnProperty.call(out, k)) out[k] = obj[k];
1081    });
1082    return out;
1083}
1084
1085function reorderDynamicPanelRows(question, rows) {
1086    if (!Array.isArray(rows)) return rows;
1087
1088    // templateElements defines the "design order" for fields inside each repeated panel
1089    const template = question && Array.isArray(question.templateElements) ? question.templateElements : [];
1090    const templateNames = template
1091        .map(el => el && el.name ? el.name : null)
1092        .filter(Boolean);
1093
1094    if (!templateNames.length) return rows;
1095
1096    return rows.map(row => reorderObjectByKeys(row, templateNames));
1097}
1098
1099function reorderDynamicMatrixRows(question, rows) {
1100    if (!Array.isArray(rows)) return rows;
1101
1102    const cols = question && Array.isArray(question.columns) ? question.columns : [];
1103    const colNames = cols
1104        .map(c => (c && (c.name || c.value)) ? (c.name || c.value) : null)
1105        .filter(Boolean);
1106
1107    if (!colNames.length) return rows;
1108
1109    return rows.map(row => reorderObjectByKeys(row, colNames));
1110}
1111
1112function reorderMultipleText(question, valueObj) {
1113    if (!valueObj || typeof valueObj !== "object" || Array.isArray(valueObj)) return valueObj;
1114
1115    const items = question && Array.isArray(question.items) ? question.items : [];
1116    const itemNames = items
1117        .map(i => i && i.name ? i.name : null)
1118        .filter(Boolean);
1119
1120    if (!itemNames.length) return valueObj;
1121
1122    return reorderObjectByKeys(valueObj, itemNames);
1123}
1124
1125/**
1126 * Builds submission data in SURVEY ORDER, and also fixes nested ordering
1127 * (Dynamic Panel / Dynamic Matrix / Multiple Text).
1128 */
1129function getOrderedData(survey) {
1130    const data = survey.data || {};
1131    const ordered = {};
1132
1133    // Survey definition order for top-level keys
1134    const questions = survey.getAllQuestions();
1135
1136    questions.forEach(q => {
1137        if (!q || !q.name) return;
1138        if (!Object.prototype.hasOwnProperty.call(data, q.name)) return;
1139
1140        const type = (typeof q.getType === "function" ? q.getType() : (q.getType || "")).toLowerCase();
1141        let val = data[q.name];
1142
1143        if (type === "paneldynamic") {
1144            val = reorderDynamicPanelRows(q, val);
1145        } else if (type === "matrixdynamic") {
1146            val = reorderDynamicMatrixRows(q, val);
1147        } else if (type === "multipletext") {
1148            val = reorderMultipleText(q, val);
1149        } else if (Array.isArray(val)) {
1150            // If it's an array of objects for some other reason, lightly normalize inner object key order
1151            // (keeps existing insertion order, but ensures deterministic output by reordering keys alphabetically is NOT desired here,
1152            // so we leave it as-is.)
1153        } else if (val && typeof val === "object") {
1154            // Nested plain objects (non-special types) - leave as-is
1155        }
1156
1157        ordered[q.name] = val;
1158    });
1159
1160    // Include any extra keys that aren't actual questions (just in case)
1161    Object.keys(data).forEach(k => {
1162        if (!Object.prototype.hasOwnProperty.call(ordered, k)) {
1163            ordered[k] = data[k];
1164        }
1165    });
1166
1167    return ordered;
1168}
1169
1170// Function to make the form read-only and semi-transparent
1171function makeFormReadOnly(sender) {
1172    // Don't prevent completion - let SurveyJS show its completion page first
1173    // Make all questions read-only
1174    sender.getAllQuestions().forEach(question => {
1175        question.readOnly = true;
1176    });
1177    
1178    // Hide the navigation buttons
1179    const navButtons = document.querySelectorAll('.sd-navigation__btn');
1180    navButtons.forEach(btn => {
1181        btn.style.display = 'none';
1182    });
1183    
1184    // Add semi-transparent overlay to the form container
1185    const formContainer = document.getElementById('surveyContainer-17');
1186    if (formContainer) {
1187        formContainer.style.opacity = '0.9';
1188        formContainer.style.pointerEvents = 'none';
1189        
1190        // Check if overlay already exists, if so remove it first
1191        const existingOverlay = document.getElementById('success-overlay-17');
1192        if (existingOverlay) {
1193            existingOverlay.remove();
1194        }
1195        
1196        // Add a success message overlay
1197        const successOverlay = document.createElement('div');
1198        successOverlay.id = 'success-overlay-17';
1199        successOverlay.style.cssText = `
1200            position: absolute;
1201            top: 0;
1202            left: 0;
1203            right: 0;
1204            bottom: 0;
1205            background: rgba(255, 255, 255, 0.5);
1206            display: flex !important;
1207            align-items: center;
1208            justify-content: center;
1209            z-index: 1000;
1210            pointer-events: none;
1211        `;
1212        
1213        const successMessage = document.createElement('div');
1214        successMessage.style.cssText = `
1215            background: rgba(76, 175, 80, 0.9);
1216            color: white;
1217            padding: 20px;
1218            border-radius: 8px;
1219            text-align: center;
1220            font-weight: bold;
1221            box-shadow: 0 4px 8px rgba(0,0,0,0.2);
1222        `;
1223        
1224                successMessage.innerHTML = "Thanks for reaching out to us, we\u0027ll be in touch soon.";
1225        
1226                
1227        successOverlay.appendChild(successMessage);
1228        
1229        // Make the form container relative positioned to contain the overlay
1230        formContainer.style.position = 'relative';
1231        formContainer.appendChild(successOverlay);
1232    }
1233}
1234
1235document.addEventListener("DOMContentLoaded", function() {
1236    survey17.render(document.getElementById("surveyContainer-17"));
1237
1238});
1239
1240
1241
1242
1243function getLeadSource() {
1244    const p = new URLSearchParams(location.search);
1245
1246    // Google click identifiers (common)
1247    const hasGclid = p.has('gclid') || p.has('gbraid') || p.has('wbraid');
1248
1249    // Fallback to UTMs if you use them
1250    const utmSource = (p.get('utm_source') || '').toLowerCase();
1251    const utmMedium = (p.get('utm_medium') || '').toLowerCase();
1252
1253    // "Google ads lead link" usually means a paid click, so treat any click id as Paid.
1254    if (hasGclid) return 'google_ads';
1255
1256    // If you tag with UTMs, this catches paid traffic too
1257    if (utmSource === 'google' && (utmMedium === 'cpc' || utmMedium === 'ppc' || utmMedium === 'paid')) return 'google_ads';
1258
1259    return 'organic_or_other';
1260}
1261
1262function getAttributionParams() {
1263  const STORAGE_KEY = 'xrx_attribution_v1';
1264  const p = new URLSearchParams(window.location.search);
1265
1266  // Pull only known keys (keeps storage tidy)
1267  const fromUrl = {
1268    // Standard UTMs
1269    utm_source:   p.get('utm_source'),
1270    utm_medium:   p.get('utm_medium'),
1271    utm_campaign: p.get('utm_campaign'),
1272    utm_term:     p.get('utm_term'),
1273    utm_content:  p.get('utm_content'),
1274
1275    // Common click IDs
1276    gclid:   p.get('gclid'),
1277    gbraid:  p.get('gbraid'),
1278    wbraid:  p.get('wbraid'),
1279    fbclid:  p.get('fbclid'),
1280    msclkid: p.get('msclkid')
1281  };
1282
1283  // Read anything already stored
1284  let stored = {};
1285  try {
1286    stored = JSON.parse(sessionStorage.getItem(STORAGE_KEY) || '{}') || {};
1287  } catch (e) {
1288    stored = {};
1289  }
1290
1291  // Merge: URL values win, but only if they are present (non-empty)
1292  const merged = { ...stored };
1293  Object.keys(fromUrl).forEach((k) => {
1294    const v = fromUrl[k];
1295    if (v !== null && v !== undefined && String(v).trim() !== '') {
1296      merged[k] = v;
1297    }
1298  });
1299
1300  // If we captured anything new, write back to sessionStorage
1301  // (Also store first_seen timestamp for troubleshooting)
1302  const hasAny =
1303    Object.values(merged).some(v => v !== null && v !== undefined && String(v).trim() !== '');
1304
1305  if (hasAny) {
1306    if (!merged.first_seen) merged.first_seen = new Date().toISOString();
1307    try {
1308      sessionStorage.setItem(STORAGE_KEY, JSON.stringify(merged));
1309    } catch (e) {
1310      // If storage fails (rare), just continue without breaking submit flow
1311    }
1312  }
1313
1314  // Return a clean object with nulls for missing keys (matches your existing shape)
1315  return {
1316    utm_source:   merged.utm_source   || null,
1317    utm_medium:   merged.utm_medium   || null,
1318    utm_campaign: merged.utm_campaign || null,
1319    utm_term:     merged.utm_term     || null,
1320    utm_content:  merged.utm_content  || null,
1321    gclid:        merged.gclid        || null,
1322    gbraid:       merged.gbraid       || null,
1323    wbraid:       merged.wbraid       || null,
1324    fbclid:       merged.fbclid       || null,
1325    msclkid:      merged.msclkid      || null
1326  };
1327}
1328
1329function classifyLeadSource(attrs) {
1330    // Paid Google
1331    if (attrs.gclid || attrs.gbraid || attrs.wbraid) return 'google_ads';
1332
1333    // Paid social (your convention)
1334    if ((attrs.utm_medium || '').toLowerCase() === 'paid_social') return 'paid_social';
1335
1336    // Catch-all social if you ever use utm_medium=social
1337    if ((attrs.utm_medium || '').toLowerCase() === 'social') return 'organic_social';
1338
1339    return 'organic_or_other';
1340}
1341
1342
1343function getGTMData() {
1344
1345    const attrs = getAttributionParams();
1346    const lead_source = classifyLeadSource(attrs);
1347    const page_location = window.location.href;
1348    const page_path = window.location.pathname;
1349
1350    window.dataLayer = window.dataLayer || [];
1351    window.dataLayer.push({
1352        event: 'formCompleted',
1353        form_name: "Get In Touch",
1354        page_path: page_path,
1355        page_location: page_location,
1356        submission_time: new Date().toISOString(),
1357
1358        // Attribution bundle
1359        lead_source: lead_source,
1360        utm_source: attrs.utm_source,
1361        utm_medium: attrs.utm_medium,
1362        utm_campaign: attrs.utm_campaign,
1363        utm_term: attrs.utm_term,
1364        utm_content: attrs.utm_content,
1365        gclid: attrs.gclid,
1366        gbraid: attrs.gbraid,
1367        wbraid: attrs.wbraid,
1368        fbclid: attrs.fbclid,
1369        msclkid: attrs.msclkid
1370    });
1371
1372}
1373
1374
1375
1376function alertResultsPayment (sender) {
1377
1378    // loop through all fields and if none of the fields have the class is-payment-dropdown, then run the non-payment alertResults
1379    const fields = sender.getAllQuestions();
1380    let hasPaymentDropdown = false;
1381    fields.forEach(field => {
1382        if (typeof field.jsonObj.class !== "undefined" && field.jsonObj.class === "is-payment-dropdown") {
1383            if (field.isVisible) {
1384                hasPaymentDropdown = true;
1385            }
1386        }
1387    });
1388    if ( !hasPaymentDropdown ) {
1389        survey17.completedHtml = `<div class="surveyjs-thankyou"><h2 class="surveyjs-thankyou__title">Get In Touch</h2><p class="surveyjs-thankyou__message">Thank you. Your form has been submitted successfully.</p></div>`;
1390        survey17.showCompletedPage = true;
1391        return alertResults(sender);
1392    }
1393
1394    // Build ordered results (definition order, not "filled" order)
1395    const orderedData = getOrderedData(sender);
1396    const results = JSON.stringify(orderedData);
1397
1398    var turnstileToken = SJT.getTokenForSubmit(turnstileFormId);
1399
1400    // Get the values from hidden input fields
1401    const formid = document.getElementById('formid-17').value;
1402    const pageurl = document.getElementById('pageurl').value;
1403    const paymentElements = document.getElementById('paymentElements-17').value;
1404
1405    // Create a new form element dynamically
1406    const form = document.createElement("form");
1407    form.method = "POST";
1408    form.action = "/service/index/proxysjs/";
1409
1410    // Function to add hidden input fields to the form
1411    function addHiddenField(name, value) {
1412        if (value !== undefined && value !== null) {
1413            let input = document.createElement("input");
1414            input.type = "hidden";
1415            input.name = name;
1416            input.value = value;
1417            form.appendChild(input);
1418        }
1419    }
1420
1421    // Append fields to the form
1422    addHiddenField("formid", formid);
1423    addHiddenField("pageurl", pageurl);
1424    addHiddenField("cf-turnstile-response", turnstileToken);
1425    addHiddenField("ajax", "1");
1426    addHiddenField("data", results);
1427    addHiddenField("paymentElements", paymentElements);
1428
1429    // If stripeToken exists, append it
1430    const stripeTokenElement = document.getElementById("stripeToken");
1431    if (stripeTokenElement) {
1432        addHiddenField("stripeToken", stripeTokenElement.value);
1433    }
1434
1435    getGTMData();
1436
1437    // Show thank you message before submitting (since form.submit() navigates away)
1438    makeFormReadOnly(sender);
1439
1440    const surveyHolder = document.querySelector('#form-17').closest('.surveyjs-holder');
1441    if (surveyHolder ) {
1442        surveyHolder.classList.add('surveyjs-submitted');
1443        surveyHolder.innerHTML = '<h2 class="form-title">Get In Touch</h2><p class="extracontent1">Redirecting you to a secure payment page ...</p>';
1444    }
1445
1446    // Append the form to the body and submit it (after showing message)
1447    document.body.appendChild(form);
1448    setTimeout(() => {
1449        form.submit();
1450    }, 500); // Small delay to let user see the thank you message
1451
1452}
1453
1454function handleFormSubmissionResult(sender, surveyHolder, status, data, isNetworkError) {
1455    const container = document.getElementById('surveyContainer-17');
1456    const completedPage = container && container.querySelector('.sd-completedpage');
1457
1458    // Clear any previous error
1459    if (container) {
1460        const existingError = container.querySelector('.surveyjs-submit-error');
1461        if (existingError) existingError.remove();
1462    }
1463
1464    // Network-level failure
1465    if (isNetworkError) {
1466        if (surveyHolder) {
1467            surveyHolder.classList.remove('surveyjs-submitted');
1468        }
1469        if (completedPage) {
1470            completedPage.style.display = 'none';
1471        }
1472        const errEl = document.createElement('p');
1473        errEl.className = 'surveyjs-submit-error';
1474        errEl.setAttribute('role', 'alert');
1475        errEl.style.color = '#b21f03';
1476        errEl.style.marginTop = '1em';
1477        errEl.textContent = 'Form error. Please check your connection and try again.';
1478        if (container) {
1479            container.appendChild(errEl);
1480        }
1481        return;
1482    }
1483
1484    // Success from backend
1485    if (status === 200 && data === 'success') {
1486        // console.log('Success: ' + data);
1487        getGTMData();
1488        setTimeout(() => {
1489            makeFormReadOnly(sender);
1490        }, 300);
1491        if (completedPage) {
1492            completedPage.style.display = '';
1493        }
1494        return;
1495    }
1496
1497    // Turnstile / robot validation failure: 403 or Cloudflare challenge body
1498    const looksLikeTurnstileFailure =
1499        status === 403 ||
1500        (data && (data.indexOf('Just a moment') !== -1 || data.indexOf('challenges.cloudflare.com') !== -1));
1501
1502    if (surveyHolder) {
1503        surveyHolder.classList.remove('surveyjs-submitted');
1504    }
1505    if (completedPage) {
1506        completedPage.style.display = 'none';
1507    }
1508
1509    const errEl = document.createElement('p');
1510    errEl.className = 'surveyjs-submit-error';
1511    errEl.setAttribute('role', 'alert');
1512    errEl.style.color = '#b21f03';
1513    errEl.style.marginTop = '1em';
1514    errEl.textContent = looksLikeTurnstileFailure
1515        ? 'Security check failed or expired. Please complete it again and resubmit.'
1516        : 'Form error. Please try again.';
1517
1518    if (container) {
1519        container.appendChild(errEl);
1520    }
1521
1522    if (looksLikeTurnstileFailure) {
1523        SJT.resetWidget(turnstileFormId);
1524        SJT.syncCompleteButton(sender, turnstileFormId);
1525    }
1526}
1527
1528function alertResults (sender) {
1529    // Build ordered results (definition order, not "filled" order)
1530    const orderedData = getOrderedData(sender);
1531    const results = JSON.stringify(orderedData);
1532    
1533    // Post these results to a url using javascript fetch or any other library
1534    // Create a new FormData object
1535    const formData = new FormData();
1536    var turnstileToken = SJT.getTokenForSubmit(turnstileFormId);
1537
1538    // Get the values from the hidden input fields
1539    const formid = document.getElementById('formid-17').value;
1540    const pageurl = document.getElementById('pageurl').value;
1541    
1542    // Get the paymentElements from the hidden input field
1543    const paymentElements = document.getElementById('paymentElements-17').value;
1544    
1545    // If the form id stripeToken exists then add it to the form data
1546    if (document.getElementById('stripeToken')) {
1547        formData.append('stripeToken', document.getElementById('stripeToken').value);
1548    }
1549
1550    // Add your data as individual key-value pairs
1551    formData.append('formid', formid);
1552    formData.append('pageurl', pageurl);
1553    formData.append('cf-turnstile-response', turnstileToken);
1554    formData.append('ajax', 1);
1555    // IMPORTANT: results is already a JSON string; DO NOT JSON.stringify it again
1556    formData.append('data', results);
1557    formData.append('paymentElements', paymentElements);
1558
1559    // Add class to surveyjs-holder on successful submission
1560    const surveyHolder = document.querySelector('#form-17').closest('.surveyjs-holder');
1561    if (surveyHolder) {
1562        surveyHolder.classList.add('surveyjs-submitted');
1563    }
1564
1565    const yOffset = -280;
1566    const y = document.querySelector('#form-17').getBoundingClientRect().top + window.pageYOffset + yOffset;
1567    window.scrollTo({ top: y, behavior: 'smooth' });
1568    
1569    // Send the FormData object using fetch
1570    // Note: 403 here is often Cloudflare blocking the POST (e.g. when payload includes file upload data).
1571    // Add a WAF/Page Rule exception for /service/index/proxysjs/ in Cloudflare if submissions with files fail.
1572    fetch('/service/index/proxysjs/', {
1573        method: 'POST',
1574        body: formData,
1575    })
1576    .then(response => {
1577        const status = response.status;
1578        return response.text().then(text => ({ status, text }));
1579    })
1580    .then(({ status, text }) => {
1581        handleFormSubmissionResult(sender, surveyHolder, status, text, false);
1582    })
1583    .catch(() => {
1584        handleFormSubmissionResult(sender, surveyHolder, 0, '', true);
1585    });
1586}
1587
1588// Validate Turnstile before allowing survey completion
1589survey17.onCompleting.add((sender, options) => {
1590    var token = SJT.getTokenForSubmit(turnstileFormId);
1591
1592    if (!token) {
1593        options.allowComplete = false;
1594        SJT.showError(turnstileFormId, 'Please complete the security check below before submitting.');
1595        SJT.syncCompleteButton(sender, turnstileFormId);
1596        return;
1597    }
1598
1599    SJT.clearError(turnstileFormId);
1600
1601        survey17.completedHtml = "\u003Cdiv class=\u0022surveyjs-thankyou\u0022\u003E\u003Ch2 class=\u0022surveyjs-thankyou__title\u0022\u003EGet In Touch\u003C\/h2\u003E\u003Cp class=\u0022surveyjs-thankyou__message\u0022\u003EThanks for reaching out to us, we\u0027ll be in touch soon.\u003C\/p\u003E\u003C\/div\u003E";
1602    });
1603survey17.onAfterRenderSurvey.add(() => {
1604    SJT.syncCompleteButton(survey17, turnstileFormId);
1605});
1606    survey17.onComplete.add(alertResults);
1607
1608    })();
1609
1610    </script>
1610
1611</div>				</div>
1612				<div class="footer-copyright footer-copyright--sm">
1613					<p>
1614						&copy; 2026 POA
1615						<span>|</span> <a href="/sitemap/">Sitemap</a>
1616						<span>|</span> <a href="/privacy-policy/">Privacy Policy</a>
1617					</p>
1618					<p>Site by <a aria-label="OracleStudio" target="_blank" rel="noopener noreferrer" href="https://www.oraclestudio.com.au">OracleStudio</a> <span>|</span>
1619						Design by <a aria-label="Novellus" target="_blank" rel="noopener noreferrer" href="javascript:;">Novellus</a></p>
1620				</div>
1621			</div>
1622			<a href="javascript:;" data-href="body" class="back-to-top scrollto">
1623				<span class="back-to-top-icon">
1624					<svg height="15.5" viewBox="0 0 15.5 15.5" width="15.5" xmlns="http://www.w3.org/2000/svg"><path d="m12 4.25.27.054.012.001.005.003c.008.002.004 0 .012.008l.231.154 7 7c.293.293.293.767 0 1.06s-.767.293-1.06 0l-5.72-5.719v12.189c0 .414-.336.75-.75.75s-.75-.336-.75-.75v-12.189l-5.72 5.719c-.293.293-.767.293-1.06 0s-.293-.767 0-1.06l7-7c.158-.113.087-.08.2-.123.108-.108.02-.035.33-.097z" fill="#001d3c" transform="translate(-4.25 -4.25)"/></svg>				</span>
1625				<span class="back-to-top-title">Top</span>
1626			</a>
1627		</footer>
1628	</div>
1629	<div class="mm-menu-bg"></div>
1630	<div class="mm-menu">
1631		<div class="mm-menu-content">
1632			<div class="mm-menu-nav"></div>
1633			<div class="mm-menu-social">
1634				<span class="h6">Let's Get <span>Social</span></span>
1635				<ul class="reset">
1636										<li>
1637						<a rel="nofollow noopener noreferrer" target="_blank" href="https://www.facebook.com/POABillboards/" aria-label="Facebook">
1638							<svg fill="none" height="19" viewBox="0 0 10 19" width="10" xmlns="http://www.w3.org/2000/svg"><path d="m9.18359 10.375h-2.63671v7.875h-3.51563v-7.875h-2.882812v-3.23438h2.882812v-2.49609c0-2.8125 1.6875-4.39453 4.25391-4.39453 1.23046 0 2.53125.246094 2.53125.246094v2.777346h-1.44141c-1.40625 0-1.82812.84375-1.82812 1.75781v2.10937h3.1289z" fill="#001d3c"/></svg>							<span>Facebook</span>
1639						</a>
1640					</li>
1641					<li>
1642						<a rel="nofollow noopener noreferrer" target="_blank" href="https://www.instagram.com/poa_billboards/" aria-label="Instagram">
1643							<svg fill="none" height="17" viewBox="0 0 16 17" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 4.20703c2.2148 0 4.043 1.82813 4.043 4.04297 0 2.25-1.8282 4.043-4.043 4.043-2.25 0-4.04297-1.793-4.04297-4.043 0-2.21484 1.79297-4.04297 4.04297-4.04297zm0 6.67967c1.44141 0 2.6016-1.16014 2.6016-2.6367 0-1.44141-1.16019-2.60156-2.6016-2.60156-1.47656 0-2.63672 1.16015-2.63672 2.60156 0 1.47656 1.19531 2.6367 2.63672 2.6367zm5.1328-6.82029c0-.52735-.4219-.94922-.9492-.94922-.5274 0-.9492.42187-.9492.94922 0 .52734.4218.94921.9492.94921.5273 0 .9492-.42187.9492-.94921zm2.6719.94921c.0703 1.30079.0703 5.20318 0 6.50388-.0703 1.2657-.3516 2.3555-1.2656 3.3047-.9141.9141-2.0391 1.1953-3.3047 1.2656-1.30081.0704-5.20315.0704-6.50393 0-1.26563-.0703-2.35547-.3515-3.30469-1.2656-.914061-.9492-1.195311-2.039-1.265624-3.3047-.0703122-1.3007-.0703122-5.20309 0-6.50388.070313-1.26562.351563-2.39062 1.265624-3.30468.94922-.914065 2.03906-1.195315 3.30469-1.265628 1.30078-.070312 5.20312-.070312 6.50393 0 1.2656.070313 2.3906.351563 3.3047 1.265628.914.91406 1.1953 2.03906 1.2656 3.30468zm-1.6875 7.87498c.4219-1.0195.3164-3.48044.3164-4.6406 0-1.125.1055-3.58594-.3164-4.64062-.2813-.66797-.8086-1.23047-1.4766-1.47657-1.0547-.42187-3.5156-.3164-4.6406-.3164-1.16016 0-3.62109-.10547-4.64062.3164-.70313.28125-1.23047.8086-1.51172 1.47657-.42188 1.05468-.31641 3.51562-.31641 4.64062 0 1.16016-.10547 3.6211.31641 4.6406.28125.7032.80859 1.2305 1.51172 1.5117 1.01953.4219 3.48046.3165 4.64062.3165 1.125 0 3.5859.1054 4.6406-.3165.668-.2812 1.2305-.8085 1.4766-1.5117z" fill="#001d3c"/></svg>							<span>Instagram</span>
1644						</a>
1645					</li>
1646					<li>
1647						<a rel="nofollow noopener noreferrer" target="_blank" href="https://www.linkedin.com/company/poabillboards" aria-label="LinkedIn">
1648							<svg width="15" height="14" viewBox="0 0 15 14" fill="none" xmlns="http://www.w3.org/2000/svg">
1649<path fill-rule="evenodd" clip-rule="evenodd" d="M0.182196 13.655H3.25363V4.4415H0.182196V13.655ZM1.71748 3.18394C2.78821 3.18394 3.45568 2.47554 3.45568 1.59154C3.43582 0.687744 2.78821 0 1.73734 0C0.686474 0 0 0.686884 0 1.59068C0 2.47554 0.666614 3.18308 1.69848 3.18308H1.71748V3.18394ZM14.3322 13.655V8.37258C14.3322 5.54241 12.8168 4.22545 10.7953 4.22545C9.16421 4.22545 8.4337 5.11978 8.02699 5.74727V4.4415H4.9547C4.99528 5.30656 4.9547 13.655 4.9547 13.655H8.02699V8.50944C8.02699 8.23486 8.04685 7.95942 8.12802 7.76316C8.34994 7.21314 8.85508 6.64332 9.70389 6.64332C10.8161 6.64332 11.2608 7.48772 11.2608 8.72635V13.6559L14.3322 13.655Z" fill="#003B4A"/>
1650</svg>
1651							<span>LinkedIn</span>
1652						</a>
1653					</li>
1654				</ul>
1655			</div>
1656		</div>
1657	</div>
1658		<div class="sticky-tab">
1659		<button data-fancybox data-src="#modal-enquire">Enquire Now</button>
1660	</div>
1661	<div id="modal-enquire" class="modal modal-enquire">
1662		<style>
1663
1664.success-overlay-21, #success-overlay-21 {
1665    display: none !important;
1666    opacity: 0 !important;
1667    visibility: hidden !important;
1668    pointer-events: none !important;
1669}
1670
1671</style>
1672<div id="form-21" class="surveyjs-holder" data-load="surveyjs" data-load-css data-load-js data-load-type="force">
1673    <input id="formid-21" type="hidden" value="21" name="formid" />
1674    <input id="pageurl" class="form-page-url" type="hidden" value="/" name="pageurl" />
1675    <input id="paymentElements-21" type="hidden" value="" name="paymentElements" />
1676	<div class="surveyjs-form-shell">
1677	<h3 class="form-title">Enquire Now</h3>
1678    <div id="surveyContainer-21"></div>
1679	</div>
1680<script>
1681
1682Survey.surveyLocalization.getLocaleStrings("en").filePlaceholder =
1683    "Drag and drop a file here or click the button below to select a file to upload.";
1684
1685
1686
1687
1688    var surveyJSON21 = {"pages":[{"name":"page1","elements":[{"type":"text","name":"question1","title":"First Name","isRequired":true},{"type":"text","name":"question2","startWithNewLine":false,"title":"Surname","isRequired":true},{"type":"text","name":"question3","title":"Company"},{"type":"text","name":"question4","startWithNewLine":false,"title":"Position"},{"type":"dropdown","name":"question5","title":"What region are you interested in?","choices":[{"value":"item1","text":"Airlie Beach"},{"value":"item2","text":"Augathella"},{"value":"item3","text":"Biloela"},{"value":"item4","text":"Brisbane"},{"value":"item5","text":"Bowen"},{"value":"item6","text":"Cairns"},{"value":"item7","text":"Charters Towers"},{"value":"item8","text":"Chinchilla"},{"value":"item9","text":"Clermont"},{"value":"item10","text":"Dalby"},{"value":"item11","text":"Emerald"},{"value":"item12","text":"Giru"},{"value":"item13","text":"Gladstone"},{"value":"item14","text":"Goondiwindi"},{"value":"item15","text":"Hervey Bay"},{"value":"item16","text":"Hughenden"},{"value":"item17","text":"Hinchinbrook"},{"value":"item18","text":"Innisfail"},{"value":"item19","text":"Julia Creek"},{"value":"item20","text":"Mackay"},{"value":"item21","text":"Maryborough"},{"value":"item22","text":"Miles"},{"value":"item23","text":"Milaa Milaa"},{"value":"item24","text":"Mount Isa"},{"value":"item25","text":"Port Douglas"},{"value":"item26","text":"Richmond"},{"value":"item27","text":"St George"},{"value":"item28","text":"Tablelands"},{"value":"item29","text":"Toowoomba"},{"value":"item30","text":"Townsville"},{"value":"item31","text":"Tully"},{"value":"item32","text":"Winton"}]},{"type":"text","name":"question6","title":"Phone Number","isRequired":true},{"type":"text","name":"question7","startWithNewLine":false,"title":"Email Address","isRequired":true,"inputType":"email"},{"type":"text","name":"question8","title":"Address","isRequired":true},{"type":"text","name":"question9","startWithNewLine":false,"title":"Suburb \/ City","isRequired":true},{"type":"text","name":"question10","title":"State","isRequired":true},{"type":"text","name":"question11","startWithNewLine":false,"title":"Postcode","isRequired":true},{"type":"comment","name":"question12","title":"Your Message"},{"type":"html","name":"turnstile-widget","title":"Security check","html":"<div id='turnstile-container-21' data-form-id='21'><div class='cf-turnstile-surveyjs' data-appearance='interaction-only' data-sitekey='0x4AAAAAAAfn5Ry99YNSWl_B' data-theme='light'><\/div><\/div>"}]}]};
1689    var survey21 = new Survey.Model(surveyJSON21);
1690
1691    // Signature pad: pen color (canvas API does not support CSS variables) and optional dimensions
1692    (function() {
1693        var survey = survey21;
1694        var root = document.documentElement;
1695        var resolved = getComputedStyle(root).getPropertyValue('--colorSecondary').trim();
1696        var sigWidth = 1400;
1697        var sigHeight = 300;
1698        survey.getAllQuestions().forEach(function(q) {
1699            if (q.getType() === 'signaturepad') {
1700                if (resolved) q.penColor = resolved;
1701                if (sigWidth != null && sigWidth > 0) q.signatureWidth = sigWidth;
1702                if (sigHeight != null && sigHeight > 0) q.signatureHeight = sigHeight;
1703            }
1704        });
1705    })();
1706
1707    (function() {
1708    var turnstileFormId = '21';
1709    var surveyTurnstile = survey21;
1710    var SJT = window.SurveyJsTurnstile;
1711
1712    survey21.onAfterRenderQuestion.add(function (survey, options) {
1713        if (options.question.name === "turnstile-widget") {
1714            const formId = turnstileFormId;
1715            const hasWidget = SJT.hasLiveWidget(formId);
1716            const hasToken = !!SJT.getTokenForSubmit(formId);
1717
1718            // Only render while visible; hidden modals refresh on Fancybox reveal.
1719            if (SJT.isContainerVisible(formId) && (!hasWidget || !hasToken)) {
1720                SJT.rerenderWidget(formId, surveyTurnstile);
1721            } else {
1722                SJT.syncCompleteButton(surveyTurnstile, formId);
1723            }
1724        } else if (options.question.getType() === "dropdown") {
1725            // Replace SurveyJS custom dropdown with native <select> (e.g. for Fancybox compatibility)
1726            const question = options.question;
1727            const root = options.htmlElement;
1728            if (root.querySelector("select.sd-dropdown-native")) return;
1729
1730            const choices = question.visibleChoices || question.choices || [];
1731            const valueKey = question.valuePropertyName || "value";
1732            const textKey = question.textPropertyName || "text";
1733
1734            const select = document.createElement("select");
1735            select.setAttribute("aria-label", question.title);
1736            select.className = "sd-input sd-dropdown sd-dropdown-native";
1737
1738            if ( question.jsonObj.class && question.jsonObj.class === "is-payment-dropdown") {
1739                select.classList.add("is-payment-dropdown");
1740            }
1741
1742            select.id = question.inputId;
1743            if (question.isRequired) select.required = true;
1744            if (question.readOnly) select.disabled = true;
1745
1746            const placeholder = question.placeholder || question.optionsCaption || "Select...";
1747            const emptyOption = document.createElement("option");
1748            emptyOption.value = "";
1749            emptyOption.textContent = placeholder;
1750            select.appendChild(emptyOption);
1751
1752            choices.forEach(function(choice) {
1753                const opt = document.createElement("option");
1754                opt.value = choice[valueKey] !== undefined ? String(choice[valueKey]) : (choice.value !== undefined ? String(choice.value) : "");
1755                opt.textContent = choice[textKey] !== undefined ? choice[textKey] : (choice.text !== undefined ? choice.text : opt.value);
1756                if (String(question.value) === opt.value) opt.selected = true;
1757                select.appendChild(opt);
1758            });
1759
1760            select.addEventListener("change", function() {
1761                question.value = this.value === "" ? undefined : this.value;
1762            });
1763
1764            const wrap = document.createElement("div");
1765            wrap.className = "sd-dropdown-native-wrapper";
1766            wrap.appendChild(select);
1767
1768            const wrapper = root.querySelector(".sv-dropdown_select-wrapper") || root.querySelector(".sd-dropdown");
1769            if (wrapper) {
1770                wrapper.replaceWith(wrap);
1771            } else {
1772                const content = root.querySelector(".sd-question__content") || root.querySelector(".sd-input");
1773                if (content) {
1774                    content.replaceWith(wrap);
1775                } else {
1776                    root.appendChild(wrap);
1777                }
1778            }
1779        }
1780    });
1781
1782
1783    survey21.applyTheme({
1784        "themeName": "defaultV2",
1785        "isPanelless": true
1786    });
1787    survey21.questionErrorLocation = "bottom";
1788
1789    (function scrollSurveyToTopOnStepChange() {
1790        var surveyModel = survey21;
1791        var formEl = document.getElementById('form-21');
1792
1793        var scrollAboveFormPx = 100;
1794
1795        function scrollToFormTop() {
1796            if (formEl) {
1797                var rect = formEl.getBoundingClientRect();
1798                var docY = window.pageYOffset || document.documentElement.scrollTop || 0;
1799                var y = rect.top + docY - scrollAboveFormPx;
1800                window.scrollTo({ top: Math.max(0, y), left: 0, behavior: 'auto' });
1801            } else {
1802                window.scrollTo({ top: 0, left: 0, behavior: 'auto' });
1803            }
1804        }
1805
1806        function scrollAfterLayout() {
1807            window.requestAnimationFrame(function () {
1808                window.requestAnimationFrame(scrollToFormTop);
1809            });
1810        }
1811
1812        surveyModel.onCurrentPageChanged.add(function () {
1813            scrollAfterLayout();
1814            SJT.syncCompleteButton(surveyModel, turnstileFormId);
1815            if (surveyModel.isLastPage && SJT.isContainerVisible(turnstileFormId)) {
1816                SJT.refreshVisibleWidgets(document.getElementById('form-' + turnstileFormId));
1817            }
1818        });
1819
1820        if (surveyModel.onShowingPreview && typeof surveyModel.onShowingPreview.add === 'function') {
1821            surveyModel.onShowingPreview.add(function () {
1822                scrollAfterLayout();
1823            });
1824        }
1825    })();
1826
1827    
1828
1829
1830
1831
1832// // Render the Survey
1833// document.addEventListener("DOMContentLoaded", function () {
1834//     $("#surveyContainer").Survey({ model: survey9 });
1835// });
1836
1837
1838
1839
1840
1841/**
1842 * IMPORTANT: SurveyJS stores sender.data as a plain JS object.
1843 * Object keys are inserted in the order the user answers questions.
1844 * This function rebuilds a new object in the SURVEY DEFINITION ORDER.
1845 */
1846function reorderObjectByKeys(obj, orderedKeys) {
1847    if (!obj || typeof obj !== "object" || Array.isArray(obj)) return obj;
1848
1849    const out = {};
1850    // first: known keys in desired order
1851    orderedKeys.forEach(k => {
1852        if (Object.prototype.hasOwnProperty.call(obj, k)) out[k] = obj[k];
1853    });
1854    // then: any remaining keys (don't lose anything)
1855    Object.keys(obj).forEach(k => {
1856        if (!Object.prototype.hasOwnProperty.call(out, k)) out[k] = obj[k];
1857    });
1858    return out;
1859}
1860
1861function reorderDynamicPanelRows(question, rows) {
1862    if (!Array.isArray(rows)) return rows;
1863
1864    // templateElements defines the "design order" for fields inside each repeated panel
1865    const template = question && Array.isArray(question.templateElements) ? question.templateElements : [];
1866    const templateNames = template
1867        .map(el => el && el.name ? el.name : null)
1868        .filter(Boolean);
1869
1870    if (!templateNames.length) return rows;
1871
1872    return rows.map(row => reorderObjectByKeys(row, templateNames));
1873}
1874
1875function reorderDynamicMatrixRows(question, rows) {
1876    if (!Array.isArray(rows)) return rows;
1877
1878    const cols = question && Array.isArray(question.columns) ? question.columns : [];
1879    const colNames = cols
1880        .map(c => (c && (c.name || c.value)) ? (c.name || c.value) : null)
1881        .filter(Boolean);
1882
1883    if (!colNames.length) return rows;
1884
1885    return rows.map(row => reorderObjectByKeys(row, colNames));
1886}
1887
1888function reorderMultipleText(question, valueObj) {
1889    if (!valueObj || typeof valueObj !== "object" || Array.isArray(valueObj)) return valueObj;
1890
1891    const items = question && Array.isArray(question.items) ? question.items : [];
1892    const itemNames = items
1893        .map(i => i && i.name ? i.name : null)
1894        .filter(Boolean);
1895
1896    if (!itemNames.length) return valueObj;
1897
1898    return reorderObjectByKeys(valueObj, itemNames);
1899}
1900
1901/**
1902 * Builds submission data in SURVEY ORDER, and also fixes nested ordering
1903 * (Dynamic Panel / Dynamic Matrix / Multiple Text).
1904 */
1905function getOrderedData(survey) {
1906    const data = survey.data || {};
1907    const ordered = {};
1908
1909    // Survey definition order for top-level keys
1910    const questions = survey.getAllQuestions();
1911
1912    questions.forEach(q => {
1913        if (!q || !q.name) return;
1914        if (!Object.prototype.hasOwnProperty.call(data, q.name)) return;
1915
1916        const type = (typeof q.getType === "function" ? q.getType() : (q.getType || "")).toLowerCase();
1917        let val = data[q.name];
1918
1919        if (type === "paneldynamic") {
1920            val = reorderDynamicPanelRows(q, val);
1921        } else if (type === "matrixdynamic") {
1922            val = reorderDynamicMatrixRows(q, val);
1923        } else if (type === "multipletext") {
1924            val = reorderMultipleText(q, val);
1925        } else if (Array.isArray(val)) {
1926            // If it's an array of objects for some other reason, lightly normalize inner object key order
1927            // (keeps existing insertion order, but ensures deterministic output by reordering keys alphabetically is NOT desired here,
1928            // so we leave it as-is.)
1929        } else if (val && typeof val === "object") {
1930            // Nested plain objects (non-special types) - leave as-is
1931        }
1932
1933        ordered[q.name] = val;
1934    });
1935
1936    // Include any extra keys that aren't actual questions (just in case)
1937    Object.keys(data).forEach(k => {
1938        if (!Object.prototype.hasOwnProperty.call(ordered, k)) {
1939            ordered[k] = data[k];
1940        }
1941    });
1942
1943    return ordered;
1944}
1945
1946// Function to make the form read-only and semi-transparent
1947function makeFormReadOnly(sender) {
1948    // Don't prevent completion - let SurveyJS show its completion page first
1949    // Make all questions read-only
1950    sender.getAllQuestions().forEach(question => {
1951        question.readOnly = true;
1952    });
1953    
1954    // Hide the navigation buttons
1955    const navButtons = document.querySelectorAll('.sd-navigation__btn');
1956    navButtons.forEach(btn => {
1957        btn.style.display = 'none';
1958    });
1959    
1960    // Add semi-transparent overlay to the form container
1961    const formContainer = document.getElementById('surveyContainer-21');
1962    if (formContainer) {
1963        formContainer.style.opacity = '0.9';
1964        formContainer.style.pointerEvents = 'none';
1965        
1966        // Check if overlay already exists, if so remove it first
1967        const existingOverlay = document.getElementById('success-overlay-21');
1968        if (existingOverlay) {
1969            existingOverlay.remove();
1970        }
1971        
1972        // Add a success message overlay
1973        const successOverlay = document.createElement('div');
1974        successOverlay.id = 'success-overlay-21';
1975        successOverlay.style.cssText = `
1976            position: absolute;
1977            top: 0;
1978            left: 0;
1979            right: 0;
1980            bottom: 0;
1981            background: rgba(255, 255, 255, 0.5);
1982            display: flex !important;
1983            align-items: center;
1984            justify-content: center;
1985            z-index: 1000;
1986            pointer-events: none;
1987        `;
1988        
1989        const successMessage = document.createElement('div');
1990        successMessage.style.cssText = `
1991            background: rgba(76, 175, 80, 0.9);
1992            color: white;
1993            padding: 20px;
1994            border-radius: 8px;
1995            text-align: center;
1996            font-weight: bold;
1997            box-shadow: 0 4px 8px rgba(0,0,0,0.2);
1998        `;
1999        
2000                successMessage.innerHTML = 'Form submitted successfully!';
2001                
2002        successOverlay.appendChild(successMessage);
2003        
2004        // Make the form container relative positioned to contain the overlay
2005        formContainer.style.position = 'relative';
2006        formContainer.appendChild(successOverlay);
2007    }
2008}
2009
2010document.addEventListener("DOMContentLoaded", function() {
2011    survey21.render(document.getElementById("surveyContainer-21"));
2012
2013});
2014
2015
2016
2017
2018function getLeadSource() {
2019    const p = new URLSearchParams(location.search);
2020
2021    // Google click identifiers (common)
2022    const hasGclid = p.has('gclid') || p.has('gbraid') || p.has('wbraid');
2023
2024    // Fallback to UTMs if you use them
2025    const utmSource = (p.get('utm_source') || '').toLowerCase();
2026    const utmMedium = (p.get('utm_medium') || '').toLowerCase();
2027
2028    // "Google ads lead link" usually means a paid click, so treat any click id as Paid.
2029    if (hasGclid) return 'google_ads';
2030
2031    // If you tag with UTMs, this catches paid traffic too
2032    if (utmSource === 'google' && (utmMedium === 'cpc' || utmMedium === 'ppc' || utmMedium === 'paid')) return 'google_ads';
2033
2034    return 'organic_or_other';
2035}
2036
2037function getAttributionParams() {
2038  const STORAGE_KEY = 'xrx_attribution_v1';
2039  const p = new URLSearchParams(window.location.search);
2040
2041  // Pull only known keys (keeps storage tidy)
2042  const fromUrl = {
2043    // Standard UTMs
2044    utm_source:   p.get('utm_source'),
2045    utm_medium:   p.get('utm_medium'),
2046    utm_campaign: p.get('utm_campaign'),
2047    utm_term:     p.get('utm_term'),
2048    utm_content:  p.get('utm_content'),
2049
2050    // Common click IDs
2051    gclid:   p.get('gclid'),
2052    gbraid:  p.get('gbraid'),
2053    wbraid:  p.get('wbraid'),
2054    fbclid:  p.get('fbclid'),
2055    msclkid: p.get('msclkid')
2056  };
2057
2058  // Read anything already stored
2059  let stored = {};
2060  try {
2061    stored = JSON.parse(sessionStorage.getItem(STORAGE_KEY) || '{}') || {};
2062  } catch (e) {
2063    stored = {};
2064  }
2065
2066  // Merge: URL values win, but only if they are present (non-empty)
2067  const merged = { ...stored };
2068  Object.keys(fromUrl).forEach((k) => {
2069    const v = fromUrl[k];
2070    if (v !== null && v !== undefined && String(v).trim() !== '') {
2071      merged[k] = v;
2072    }
2073  });
2074
2075  // If we captured anything new, write back to sessionStorage
2076  // (Also store first_seen timestamp for troubleshooting)
2077  const hasAny =
2078    Object.values(merged).some(v => v !== null && v !== undefined && String(v).trim() !== '');
2079
2080  if (hasAny) {
2081    if (!merged.first_seen) merged.first_seen = new Date().toISOString();
2082    try {
2083      sessionStorage.setItem(STORAGE_KEY, JSON.stringify(merged));
2084    } catch (e) {
2085      // If storage fails (rare), just continue without breaking submit flow
2086    }
2087  }
2088
2089  // Return a clean object with nulls for missing keys (matches your existing shape)
2090  return {
2091    utm_source:   merged.utm_source   || null,
2092    utm_medium:   merged.utm_medium   || null,
2093    utm_campaign: merged.utm_campaign || null,
2094    utm_term:     merged.utm_term     || null,
2095    utm_content:  merged.utm_content  || null,
2096    gclid:        merged.gclid        || null,
2097    gbraid:       merged.gbraid       || null,
2098    wbraid:       merged.wbraid       || null,
2099    fbclid:       merged.fbclid       || null,
2100    msclkid:      merged.msclkid      || null
2101  };
2102}
2103
2104function classifyLeadSource(attrs) {
2105    // Paid Google
2106    if (attrs.gclid || attrs.gbraid || attrs.wbraid) return 'google_ads';
2107
2108    // Paid social (your convention)
2109    if ((attrs.utm_medium || '').toLowerCase() === 'paid_social') return 'paid_social';
2110
2111    // Catch-all social if you ever use utm_medium=social
2112    if ((attrs.utm_medium || '').toLowerCase() === 'social') return 'organic_social';
2113
2114    return 'organic_or_other';
2115}
2116
2117
2118function getGTMData() {
2119
2120    const attrs = getAttributionParams();
2121    const lead_source = classifyLeadSource(attrs);
2122    const page_location = window.location.href;
2123    const page_path = window.location.pathname;
2124
2125    window.dataLayer = window.dataLayer || [];
2126    window.dataLayer.push({
2127        event: 'formCompleted',
2128        form_name: "Enquire Now",
2129        page_path: page_path,
2130        page_location: page_location,
2131        submission_time: new Date().toISOString(),
2132
2133        // Attribution bundle
2134        lead_source: lead_source,
2135        utm_source: attrs.utm_source,
2136        utm_medium: attrs.utm_medium,
2137        utm_campaign: attrs.utm_campaign,
2138        utm_term: attrs.utm_term,
2139        utm_content: attrs.utm_content,
2140        gclid: attrs.gclid,
2141        gbraid: attrs.gbraid,
2142        wbraid: attrs.wbraid,
2143        fbclid: attrs.fbclid,
2144        msclkid: attrs.msclkid
2145    });
2146
2147}
2148
2149
2150
2151function alertResultsPayment (sender) {
2152
2153    // loop through all fields and if none of the fields have the class is-payment-dropdown, then run the non-payment alertResults
2154    const fields = sender.getAllQuestions();
2155    let hasPaymentDropdown = false;
2156    fields.forEach(field => {
2157        if (typeof field.jsonObj.class !== "undefined" && field.jsonObj.class === "is-payment-dropdown") {
2158            if (field.isVisible) {
2159                hasPaymentDropdown = true;
2160            }
2161        }
2162    });
2163    if ( !hasPaymentDropdown ) {
2164        survey21.completedHtml = `<div class="surveyjs-thankyou"><h2 class="surveyjs-thankyou__title">Enquire Now</h2><p class="surveyjs-thankyou__message">Thank you. Your form has been submitted successfully.</p></div>`;
2165        survey21.showCompletedPage = true;
2166        return alertResults(sender);
2167    }
2168
2169    // Build ordered results (definition order, not "filled" order)
2170    const orderedData = getOrderedData(sender);
2171    const results = JSON.stringify(orderedData);
2172
2173    var turnstileToken = SJT.getTokenForSubmit(turnstileFormId);
2174
2175    // Get the values from hidden input fields
2176    const formid = document.getElementById('formid-21').value;
2177    const pageurl = document.getElementById('pageurl').value;
2178    const paymentElements = document.getElementById('paymentElements-21').value;
2179
2180    // Create a new form element dynamically
2181    const form = document.createElement("form");
2182    form.method = "POST";
2183    form.action = "/service/index/proxysjs/";
2184
2185    // Function to add hidden input fields to the form
2186    function addHiddenField(name, value) {
2187        if (value !== undefined && value !== null) {
2188            let input = document.createElement("input");
2189            input.type = "hidden";
2190            input.name = name;
2191            input.value = value;
2192            form.appendChild(input);
2193        }
2194    }
2195
2196    // Append fields to the form
2197    addHiddenField("formid", formid);
2198    addHiddenField("pageurl", pageurl);
2199    addHiddenField("cf-turnstile-response", turnstileToken);
2200    addHiddenField("ajax", "1");
2201    addHiddenField("data", results);
2202    addHiddenField("paymentElements", paymentElements);
2203
2204    // If stripeToken exists, append it
2205    const stripeTokenElement = document.getElementById("stripeToken");
2206    if (stripeTokenElement) {
2207        addHiddenField("stripeToken", stripeTokenElement.value);
2208    }
2209
2210    getGTMData();
2211
2212    // Show thank you message before submitting (since form.submit() navigates away)
2213    makeFormReadOnly(sender);
2214
2215    const surveyHolder = document.querySelector('#form-21').closest('.surveyjs-holder');
2216    if (surveyHolder ) {
2217        surveyHolder.classList.add('surveyjs-submitted');
2218        surveyHolder.innerHTML = '<h2 class="form-title">Enquire Now</h2><p class="extracontent1">Redirecting you to a secure payment page ...</p>';
2219    }
2220
2221    // Append the form to the body and submit it (after showing message)
2222    document.body.appendChild(form);
2223    setTimeout(() => {
2224        form.submit();
2225    }, 500); // Small delay to let user see the thank you message
2226
2227}
2228
2229function handleFormSubmissionResult(sender, surveyHolder, status, data, isNetworkError) {
2230    const container = document.getElementById('surveyContainer-21');
2231    const completedPage = container && container.querySelector('.sd-completedpage');
2232
2233    // Clear any previous error
2234    if (container) {
2235        const existingError = container.querySelector('.surveyjs-submit-error');
2236        if (existingError) existingError.remove();
2237    }
2238
2239    // Network-level failure
2240    if (isNetworkError) {
2241        if (surveyHolder) {
2242            surveyHolder.classList.remove('surveyjs-submitted');
2243        }
2244        if (completedPage) {
2245            completedPage.style.display = 'none';
2246        }
2247        const errEl = document.createElement('p');
2248        errEl.className = 'surveyjs-submit-error';
2249        errEl.setAttribute('role', 'alert');
2250        errEl.style.color = '#b21f03';
2251        errEl.style.marginTop = '1em';
2252        errEl.textContent = 'Form error. Please check your connection and try again.';
2253        if (container) {
2254            container.appendChild(errEl);
2255        }
2256        return;
2257    }
2258
2259    // Success from backend
2260    if (status === 200 && data === 'success') {
2261        // console.log('Success: ' + data);
2262        getGTMData();
2263        setTimeout(() => {
2264            makeFormReadOnly(sender);
2265        }, 300);
2266        if (completedPage) {
2267            completedPage.style.display = '';
2268        }
2269        return;
2270    }
2271
2272    // Turnstile / robot validation failure: 403 or Cloudflare challenge body
2273    const looksLikeTurnstileFailure =
2274        status === 403 ||
2275        (data && (data.indexOf('Just a moment') !== -1 || data.indexOf('challenges.cloudflare.com') !== -1));
2276
2277    if (surveyHolder) {
2278        surveyHolder.classList.remove('surveyjs-submitted');
2279    }
2280    if (completedPage) {
2281        completedPage.style.display = 'none';
2282    }
2283
2284    const errEl = document.createElement('p');
2285    errEl.className = 'surveyjs-submit-error';
2286    errEl.setAttribute('role', 'alert');
2287    errEl.style.color = '#b21f03';
2288    errEl.style.marginTop = '1em';
2289    errEl.textContent = looksLikeTurnstileFailure
2290        ? 'Security check failed or expired. Please complete it again and resubmit.'
2291        : 'Form error. Please try again.';
2292
2293    if (container) {
2294        container.appendChild(errEl);
2295    }
2296
2297    if (looksLikeTurnstileFailure) {
2298        SJT.resetWidget(turnstileFormId);
2299        SJT.syncCompleteButton(sender, turnstileFormId);
2300    }
2301}
2302
2303function alertResults (sender) {
2304    // Build ordered results (definition order, not "filled" order)
2305    const orderedData = getOrderedData(sender);
2306    const results = JSON.stringify(orderedData);
2307    
2308    // Post these results to a url using javascript fetch or any other library
2309    // Create a new FormData object
2310    const formData = new FormData();
2311    var turnstileToken = SJT.getTokenForSubmit(turnstileFormId);
2312
2313    // Get the values from the hidden input fields
2314    const formid = document.getElementById('formid-21').value;
2315    const pageurl = document.getElementById('pageurl').value;
2316    
2317    // Get the paymentElements from the hidden input field
2318    const paymentElements = document.getElementById('paymentElements-21').value;
2319    
2320    // If the form id stripeToken exists then add it to the form data
2321    if (document.getElementById('stripeToken')) {
2322        formData.append('stripeToken', document.getElementById('stripeToken').value);
2323    }
2324
2325    // Add your data as individual key-value pairs
2326    formData.append('formid', formid);
2327    formData.append('pageurl', pageurl);
2328    formData.append('cf-turnstile-response', turnstileToken);
2329    formData.append('ajax', 1);
2330    // IMPORTANT: results is already a JSON string; DO NOT JSON.stringify it again
2331    formData.append('data', results);
2332    formData.append('paymentElements', paymentElements);
2333
2334    // Add class to surveyjs-holder on successful submission
2335    const surveyHolder = document.querySelector('#form-21').closest('.surveyjs-holder');
2336    if (surveyHolder) {
2337        surveyHolder.classList.add('surveyjs-submitted');
2338    }
2339
2340    const yOffset = -280;
2341    const y = document.querySelector('#form-21').getBoundingClientRect().top + window.pageYOffset + yOffset;
2342    window.scrollTo({ top: y, behavior: 'smooth' });
2343    
2344    // Send the FormData object using fetch
2345    // Note: 403 here is often Cloudflare blocking the POST (e.g. when payload includes file upload data).
2346    // Add a WAF/Page Rule exception for /service/index/proxysjs/ in Cloudflare if submissions with files fail.
2347    fetch('/service/index/proxysjs/', {
2348        method: 'POST',
2349        body: formData,
2350    })
2351    .then(response => {
2352        const status = response.status;
2353        return response.text().then(text => ({ status, text }));
2354    })
2355    .then(({ status, text }) => {
2356        handleFormSubmissionResult(sender, surveyHolder, status, text, false);
2357    })
2358    .catch(() => {
2359        handleFormSubmissionResult(sender, surveyHolder, 0, '', true);
2360    });
2361}
2362
2363// Validate Turnstile before allowing survey completion
2364survey21.onCompleting.add((sender, options) => {
2365    var token = SJT.getTokenForSubmit(turnstileFormId);
2366
2367    if (!token) {
2368        options.allowComplete = false;
2369        SJT.showError(turnstileFormId, 'Please complete the security check below before submitting.');
2370        SJT.syncCompleteButton(sender, turnstileFormId);
2371        return;
2372    }
2373
2374    SJT.clearError(turnstileFormId);
2375
2376        survey21.completedHtml = '<div class="surveyjs-thankyou"><h2 class="surveyjs-thankyou__title">Enquire Now</h2><p class="surveyjs-thankyou__message">Thank you. Your form has been submitted successfully.</p></div>';
2377    });
2378survey21.onAfterRenderSurvey.add(() => {
2379    SJT.syncCompleteButton(survey21, turnstileFormId);
2380});
2381    survey21.onComplete.add(alertResults);
2382
2383    })();
2384
2385    </script>
2385
2386</div>	</div>
2387		
2387<script nonce="WWpGbVlXTTBZVFUzWVdJNE16QXk=" src="/templates/oracle/js/home-min.js?ver=1404"></script>
2387
2388	
2388<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"edb415346577442dba64a21004705484","r":1,"spa":2}' crossorigin="anonymous"></script>
2388
2389</body>
2390</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.