skip to content link
Submit RFP
Aurora Weddings by Centric Events — Phoenix Wedding Lighting & Drape
Now booking Spring & Fall 2026

Where your
wedding vision
comes to life.

Aurora by Centric Events has been designing and producing Arizona's most beautiful weddings since 2013 — lighting, drape, rentals, AV, staging and the crew who makes it all happen. From your first Pinterest board to the last song of the night, you work with one team, end to end.

One design team. One install crew. One point of contact — from first sketch to last dance.
Request a quote · step 1 / 2

Start here.

We reply within one business day · No spam · A real producer on the Valley floor.

Proudly producing at
Arizona Biltmore Wrigley Mansion Hotel Valley Ho El Chorro Omni Montelucia Sanctuary Gainey Ranch McCormick Ranch Andaz Scottsdale Arizona Biltmore Wrigley Mansion Hotel Valley Ho El Chorro Omni Montelucia Sanctuary Gainey Ranch McCormick Ranch Andaz Scottsdale
The Aurora difference

Aurora is what happens when Arizona’s largest event-production company turns its full toolbox toward one couple at a time.

Same trucks. Same crews. Same install standards we bring to Carvana, Dutch Bros, and the Phoenix Open — turned toward your venue, your colors, your moment.

One producer. One bill. One focus: your day.

A few of our nights

From this last season.

The toolbox

Everything your day needs, under one roof.

— 01

Lighting + Drape Package

Our signature. Designed and run together.

— 02

Chandeliers & Pendants

Crystal, iron-lantern, brass. Up to 30 ft.

— 03

Ceiling Drape & Swags

Ivory, champagne, blush, smoke — or a custom swatch.

— 04

Bistro & String Lights

Warm 2200K café, fairy strands, icicle drops.

— 05

Uplighting

40+ wireless LEDs, programmed to your palette.

— 06

Pipe & Drape Walls

Largest inventory in the Southwest.

— 07

Dance Floors & Stages

Up to 40×40 ft, custom monogram vinyl.

— 08

Wedding A/V

Mics, speakers, projection, screens. Engineered and run.

— 09

GOBO & Monogram Projection

Steel or glass. Your name in light.

— 10

Special Effects

Sparklers, confetti, low-fog, geysers. Indoor-safe.

— 11

Themed & Custom Rentals

If you can sketch it, we can build it.

← swipe or scroll to explore →

The portfolio

A few nights from the last few seasons.

“Our reception looked like a film set. Worth every penny.”
A. & D.
Arizona Biltmore · Oct 2025
“We handed them our Pinterest board. They delivered the real thing — better.”
P. & J.
El Chorro · Jun 2025
“The drape transformed the ballroom. Featured on two blogs since.”
M. & E.
Omni Montelucia · Apr 2025
“One team. One bill. Magic.”
R. & S.
Wrigley Mansion · 2024
Also trusted by
The Knot
WeddingWire
Junebug Weddings
Phoenix Magazine
What happens next

From inquiry to first dance.

i.

Same-day reply

A real producer reads your inquiry the same business day.

ii.

48-hour quote

Tailored to your venue, your colors, your night.

iii.

Free site walk

Meet on-site. Walk the room. No deposit until you say yes.

Saturdays fill 8–10 months ahead

Light your day.

A producer replies within one business day — always.

Request your quote   →
© 2026 Aurora · a Centric Events studio · 2620 E Greenway Rd Ste 106, Phoenix, AZ
flag, so it no-ops if the data URI version already ran. Wrapped in display:none host so leaked text (if WP strips
elsewhere on the // page. All of your existing Fluent Forms notifications, lead // routing, integrations, and confirmations keep working unchanged // (no new endpoints, no API keys). // // If the hidden Fluent Form isn't found, the form falls back to // a mailto: to FALLBACK_EMAIL so leads aren't lost. // // IMPORTANT — Wrapped in DOMContentLoaded so it runs even if some // WordPress block runs the script in an unexpected order. Also // idempotent (won't double-bind if executed twice). // ============================================================ (function(){ function ready(fn) { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', fn); } else { fn(); } } ready(function init() { if (window.__auroraInited) return; // idempotent window.__auroraInited = true; var FALLBACK_EMAIL = 'hello@centric.events'; // Fluent Forms field-name aliases. Each landing-page field // tries these in order; first match wins. If your Fluent Form // uses different names, add them to the front of the list. // // SERVICES is special: the chip selections get formatted into // a friendly sentence and routed to your "How can we help" // free-text box (under the `message`/`how_can_we_help` keys). // Field name aliases. The FIRST entry in each list is what your // current Fluent Form (id=1) uses, based on the field labels you // confirmed: First Name, Last Name, Phone Number, Email, // Event Location, Event Date, Services of Interest, How did // you hear about us?, Message. var FF_FIELD_ALIASES = { email: ['email', 'email_address'], firstname: ['first_name', 'names[first_name]', 'firstname', 'fname'], lastname: ['last_name', 'names[last_name]', 'lastname', 'lname'], phone: ['phone', 'phone_number', 'tel'], wedding_date: ['event_date', 'wedding_date', 'date', 'datetime'], venue: ['event_location', 'venue', 'event_venue', 'location', 'wedding_venue', 'address'], message: ['message', 'how_can_we_help', 'how_can_we_help_you', 'inquiry', 'notes', 'details', 'description', 'comments', 'textarea'], // Hardcoded auto-fills - never asked on the styled form, // sent invisibly behind the scenes. services_of_interest: ['services_of_interest', 'service_of_interest', 'services_interest', 'services'], how_did_you_hear: ['how_did_you_hear_about_us', 'how_did_you_hear', 'how_heard', 'source', 'lead_source', 'referrer'] }; var form = document.getElementById('auroraForm'); if (!form) { console.warn('[Aurora] #auroraForm not found on page.'); return; } // ============================================================ // GLOBAL CTA NUKE — find and hide any fixed/sticky widget // outside our page that says "Get a Quote", "Request a Quote", // "Submit RFP", or similar. Catches plugin/theme-injected // floating buttons that CSS can't reliably target. // // Runs on init + 500ms + 1500ms to catch lazy-injected widgets. // ============================================================ function nukeGlobalCTAs() { var KILL_TEXT = /^(get\s*a\s*quote|request\s*a\s*quote|submit\s*rfp|book\s*now|chat\s*with\s*us|contact\s*us|free\s*quote|free\s*consultation)$/i; var els = document.querySelectorAll('a, button, div, span'); for (var i = 0; i < els.length; i++) { var el = els[i]; if (el.closest('.aurora-page')) continue; // ours, leave alone if (el.closest('.aurora-script-host')) continue; // also ours var style = window.getComputedStyle(el); if (style.position !== 'fixed' && style.position !== 'sticky') continue; var t = (el.textContent || '').trim(); if (!t || t.length > 40) continue; if (KILL_TEXT.test(t)) { // climb to the outermost wrapper that's still position:fixed var n = el; while (n.parentElement) { var ps = window.getComputedStyle(n.parentElement); if ((ps.position === 'fixed' || ps.position === 'sticky') && !n.parentElement.closest('.aurora-page') && n.parentElement.tagName !== 'BODY') { n = n.parentElement; } else break; } n.style.setProperty('display', 'none', 'important'); n.setAttribute('data-aurora-killed', '1'); } } } nukeGlobalCTAs(); setTimeout(nukeGlobalCTAs, 500); setTimeout(nukeGlobalCTAs, 1500); setTimeout(nukeGlobalCTAs, 4000); // ---- Step navigation ---- var steps = form.querySelectorAll('[data-step]'); function showStep(target) { steps.forEach(function(s){ var is = String(s.getAttribute('data-step')) === String(target); s.hidden = !is; }); } // Step nav buttons (Continue / Back). Use preventDefault + // stopPropagation so a button without an explicit type can't // accidentally submit the form. form.addEventListener('click', function(e){ var el = e.target.closest('[data-go]'); if (!el) return; e.preventDefault(); e.stopPropagation(); var go = el.getAttribute('data-go'); if (go === '2') { var email = form.querySelector('input[name="email"]'); if (!email || !email.value || email.value.indexOf('@') < 0) { if (email) { email.focus(); email.style.borderColor = '#E07A5F'; } return; } } showStep(go); }, true); // capture phase, so we run before any default form handlers // Pressing Enter on Step 1's email input should advance to Step 2, // not submit the form (which would only have the email field set // and trigger fallback mailto). form.addEventListener('keydown', function(e){ if (e.key !== 'Enter') return; var step1 = form.querySelector('[data-step="1"]'); if (step1 && !step1.hidden) { e.preventDefault(); var btn = step1.querySelector('[data-go="2"]'); if (btn) btn.click(); } }); // ---- Service chips (multi-select) ---- var selected = new Set(); var chipsEl = document.getElementById('auroraChips'); if (chipsEl) { chipsEl.addEventListener('click', function(e){ var chip = e.target.closest('.chip'); if (!chip) return; var svc = chip.getAttribute('data-svc'); if (selected.has(svc)) { selected.delete(svc); chip.classList.remove('active'); } else { selected.add(svc); chip.classList.add('active'); } document.getElementById('auroraServices').value = Array.from(selected).join(', '); }); } // ============================================================ // SUBMISSION_URL - admin-ajax.php. Prefer FF's localized one if // it's set on the page (window.fluent_forms_global_var.ajaxurl). // Falls back to the form's action attribute. // ============================================================ var SUBMISSION_URL = (window.fluent_forms_global_var && window.fluent_forms_global_var.ajaxurl) || form.getAttribute('action') || (location.origin + '/wp-admin/admin-ajax.php'); var SUBMISSION_OK = !!SUBMISSION_URL; // ============================================================ // SUBMIT HANDLER — POST to the Fluent Forms Incoming Webhook // ============================================================ // // Two layers of reliability: // 1. Native HTML form POST (action=WEBHOOK_URL target=iframe) // always runs — even if every line of this JS gets stripped // by WordPress. The hidden iframe catches the response so // the user stays on this page. // 2. THIS JS handler intercepts the submit, posts via fetch() // so we can show the in-page "Thank you" panel and detect // errors. If fetch() fails, we let the native post happen // (return without preventDefault) so the form still submits. // // Webhook URL comes from the form's `action` attribute. To swap: // change action="..." on
. // ============================================================ form.addEventListener('submit', function(e){ var data = {}; form.querySelectorAll('input').forEach(function(input){ if (!input.name) return; data[input.name] = input.value; }); // Chip selections \u2192 "Message" textarea (free-text on FF form 1) var lines = []; if (data.services) lines.push('Services interested in: ' + data.services + '.'); if (data.source) lines.push('Lead source: ' + data.source + '.'); if (lines.length) data.message = lines.join('\n\n'); delete data.services; delete data.source; // we route this via how_did_you_hear instead // ============================================================ // Auto-fills for required FF dropdowns the user never sees. // Services of Interest \u2192 always "Wedding" (the form's // event-type categorizer) // How did you hear about us? \u2192 always "Wedding Show" // (must match a dropdown option in FF) // If FF rejects either value, add it as a dropdown option in // Form 1 and re-test, OR change the strings here. // ============================================================ data.services_of_interest = 'Wedding'; data.how_did_you_hear = 'Wedding Show'; if (!SUBMISSION_OK) { console.error('[Aurora] Submission URL is not set. Update the form action= attribute.'); return; // let native submit happen so user isn't stuck } e.preventDefault(); e.stopPropagation(); var submitBtn = form.querySelector('button[type="submit"]'); var originalLabel = submitBtn ? submitBtn.innerHTML : ''; if (submitBtn) { submitBtn.disabled = true; submitBtn.innerHTML = 'Sending…'; } function showThanks() { var first = (data.firstname || data.email || '').trim(); var clean = first.split(' ')[0].replace(/[^A-Za-z\-']/g,''); var label = clean ? 'Thank you, ' + clean + '.' : 'Thank you.'; var thanks = document.getElementById('auroraThanksName'); if (thanks) thanks.textContent = label; showStep('done'); if (typeof window.dataLayer !== 'undefined') { window.dataLayer.push({ event: 'aurora_lead_submitted', source: data.source }); } } function softFail(reason) { console.error('[Aurora] Submission failed:', reason, data); var thanks = document.getElementById('auroraThanksName'); if (thanks) thanks.textContent = 'Thank you.'; var doneStep = form.querySelector('[data-step="done"]'); if (doneStep) { var p = doneStep.querySelector('p'); if (p) p.innerHTML = 'We had trouble sending your inquiry automatically. Please email ' + '' + FALLBACK_EMAIL + '' + ' or call (602) 687-6169.'; } showStep('done'); if (submitBtn) { submitBtn.disabled = false; submitBtn.innerHTML = originalLabel; } } // ============================================================ // Build the request the way Fluent Forms' own JS does it. // // FF's admin-ajax handler at action=fluentform_submit expects: // action = 'fluentform_submit' // form_id = // data = URL-encoded string of all the form fields, // INCLUDING the nonce (named like _fluentform_N_fluentformnonce) // // We can't just send each field as a separate POST entry - FF // will return "No corresponding form found" (HTTP 422). The // payload shape has to match. // ============================================================ var ffForm = findFluentForm(); if (!ffForm) { softFail( 'Hidden Fluent Form did not render. Make sure the
Request Quote Form - Long
' + 'shortcode is being processed by WordPress (it lives in the .aurora-fluent-host div).' ); return; } // Get form_id from the form's data attribute (where FF stores it) var formId = ffForm.getAttribute('data-form_id') || (ffForm.querySelector('input[name="form_id"]') && ffForm.querySelector('input[name="form_id"]').value) || '1'; console.log('[Aurora] Hidden FF form found. form_id =', formId); // Diagnostic: log every field name on the rendered FF form. // Use this to confirm our aliases line up with the real input names. var allFFFields = Array.prototype.slice.call(ffForm.querySelectorAll('input, textarea, select')) .map(function(el) { return el.name + ' (' + (el.tagName.toLowerCase()) + (el.type ? ':'+el.type : '') + ')'; }) .filter(function(s) { return s.indexOf('(') > 0 && s[0] !== ' '; }); console.log('[Aurora] FF form has these fields:', allFFFields); // Helper: set value on an input, dispatch events. For SELECT, // verify the option actually exists or warn loudly. function setInput(input, value, fieldKey) { if (input.tagName === 'SELECT') { // Try to find an option matching our value (exact, then case-insensitive) var found = null; var lcValue = String(value).toLowerCase(); for (var i = 0; i < input.options.length; i++) { var opt = input.options[i]; if (opt.value === value || opt.text === value) { found = opt.value; break; } if (opt.value.toLowerCase() === lcValue || opt.text.toLowerCase() === lcValue) { found = opt.value; break; } } if (found !== null) { input.value = found; } else { var availableOpts = Array.prototype.slice.call(input.options).map(function(o){ return o.text; }); console.warn('[Aurora] Cannot set