Deprecated: Merkulove\Readabler\Unity\MobileDetect::__construct(): Implicitly marking parameter $headers as nullable is deprecated, the explicit nullable type must be used instead in /home/vwarranty/public_html/wp-content/plugins/readabler/src/Merkulove/Unity/MobileDetect.php on line 710

Deprecated: Merkulove\Readabler\Unity\MobileDetect::__construct(): Implicitly marking parameter $userAgent as nullable is deprecated, the explicit nullable type must be used instead in /home/vwarranty/public_html/wp-content/plugins/readabler/src/Merkulove/Unity/MobileDetect.php on line 710
Extended Warranty: Does It Cover Diagnostics?

Does My Extended Warranty Cover Diagnostics?

You take your car to the shop. The mechanic says, “We need to run a diagnostic test first.” Then they hand you a bill for $150 just to look at the car. You stare at the paper and think — wait, I have an extended warranty. Why am I paying for this? If this has ever happened to you, you are not alone. A lot of car owners feel confused and even frustrated when they find out their extended warranty does not always cover diagnostic fees. But the truth is a little more complex than a simple yes or no.

What Is a Diagnostic Fee and Why Do Shops Charge It?

The Real Purpose of a Car Diagnostic Test

A diagnostic test is when a mechanic connects a special tool to your car’s computer system to check what is wrong. Think of it like going to the doctor. Before the doctor gives you medicine, they run tests to find out what is making you sick. A car diagnostic does the same thing — it tells the mechanic which part of your car is having a problem.

Modern cars have something called an OBD-II system (On-Board Diagnostics). This system stores error codes called trouble codes when something goes wrong. The mechanic reads these codes using a scan tool. The scan can take anywhere from 30 minutes to several hours, depending on how complex the problem is. Shops charge for this time just like they charge for any other labor.

Diagnostic fees usually range from $100 to $200 at most repair shops and dealerships. Some places charge even more for advanced or multi-system diagnostics. The fee covers the technician’s time, the equipment used, and the expertise needed to read and understand what the codes mean.

Why Shops Do Not Always Roll It Into the Repair Bill

Here is where a lot of people get frustrated. You might expect the diagnostic fee to disappear if you go ahead and get the repair done. Some shops do waive it. But many do not — especially if the diagnosis shows a problem that is not covered under your warranty.

I once took my old sedan in for a strange vibration, fully expecting my service contract to handle everything. The dealer ran the test, found a worn wheel bearing, and told me it was not covered under my plan. I still had to pay $140 just for the diagnostic. It felt unfair, but the shop was within its rights. The mechanic had already spent time and used equipment to find the answer.

The key point here is this: the diagnostic is a service in itself. It is separate from the actual repair. And whether your extended warranty pays for it depends entirely on what type of plan you have and what your contract says.

Does My Extended Warranty Cover Diagnostics? The Real Answer

It Depends on Your Warranty Type and Provider

The short answer is: sometimes yes, sometimes no. Most standard extended warranties do not automatically cover diagnostic fees. But some premium plans do include them — especially if the diagnostic leads to a covered repair.

According to the Federal Trade Commission (FTC), extended warranties — technically called vehicle service contracts — cover specific repairs outlined in your contract. If diagnostics are not listed as a covered expense, the warranty provider has no legal obligation to pay for them. 

Some bumper-to-bumper extended warranties (the most comprehensive type) will cover diagnostic costs if the problem found is something the warranty covers. But powertrain-only or drivetrain-only plans are far less likely to include diagnostics in their coverage.

According to a 2024 report by ConsumerAffairs, many extended warranties do not cover the cost of diagnosing a problem — only the repair itself. This means you could pay $100 to $200 or more just to identify an issue, even if the warranty ultimately covers the fix. Full details here: 

What Happens If the Problem Is Covered?

Here is the good news. If your car has a problem that falls within your warranty’s coverage, most reputable dealerships and warranty providers will waive the diagnostic fee or fold it into the approved warranty claim. In other words, if the test confirms a covered repair, you usually do not pay for the test separately.

But there is a catch. The warranty company does not just take the shop’s word for it. They need to approve the claim first. That means the shop calls your warranty provider, explains what they found, and waits for authorization. Only after that approval does the diagnostic fee often get included in the total covered amount.

If the diagnostic reveals something not covered — like normal wear and tear, accidental damage, or a part not listed in your contract — you are on the hook for the diagnostic fee. And sometimes the repair costs too.

Types of Extended Warranties and How They Handle Diagnostics

Types of Extended Warranties and How They Handle Diagnostics

Bumper-to-Bumper vs. Powertrain Coverage

Not all extended warranties are the same. There are three main types, and each handles diagnostic coverage very differently.

A bumper-to-bumper warranty is the most complete type of extended coverage. It covers almost every system in your car — electrical, cooling, air conditioning, and more. These plans are the most likely to include or approve diagnostic fees when a covered repair is confirmed.

A powertrain warranty only covers the big stuff — your engine, transmission, and drivetrain. If you bring your car in for an electrical issue or an AC problem, your powertrain warranty will not help. And it likely will not cover the diagnostic fee for those problems either.

Some plans are called named-component plans — they list specific covered parts. If the diagnostic shows a problem with a listed part, there is a decent chance the fee gets covered. If not, you pay.

Honestly, the biggest lesson I learned after my own warranty headache was this: always read your contract before you need it. Most people (myself included) only read it when something goes wrong — and by then it is too late to change anything.

Third-Party Warranty Providers vs. Manufacturer Plans

There is also a big difference between a manufacturer’s extended warranty and one sold by a third-party company. Manufacturer plans — like Ford’s ESP or Toyota’s Gold plan — tend to be clearer and more consistent about what they cover. If you take your Ford to a Ford dealer and the repair is covered, the diagnostic fee is almost always included.

Third-party warranty companies vary wildly. Some are fantastic — they cover diagnostics, approve claims quickly, and pay the shop directly. Others are slow, deny claims for small reasons, and make you pay out of pocket and wait for reimbursement. In 2024, the FTC took action against a well-known warranty provider for not covering repairs as advertised.

So before you buy any extended warranty, ask directly: “Does this plan cover diagnostic fees?” Get the answer in writing. If the salesperson cannot answer that clearly, that tells you something important.

When Can a Dealer Charge You a Diagnostic Fee Even With a Warranty?

The Problem Cannot be reproduced.d

This is one of the most common situations that leads to a diagnostic fee dispute. You bring in your car because it makes a strange noise,se or the check engine light flickered once. But when the technician looks at it, the car acts perfectly normal. No codes, no visible problem, nothing to show the warranty company.

In this case, the dealer cannot file a warranty claim because there is nothing to claim. They spent time and labor on the diagnosis, and someone has to pay for that time. Since the warranty company will not cover a repair that was not found, the fee often falls on you.

This is frustrating, I know. But keeping detailed records actually helps a lot here. If you note exactly when the issue happens, take a short video of it, or write down the conditions — speed, temperature, road type — it makes it far easier for the mechanic to reproduce the problem and support a warranty claim.

The Issue Is Not Covered Under Your Plan

Another common scenario: the technician finds the exact problem, but it turns out to be something your warranty does not cover. Maybe it is a worn brake pad, a cracked windshield washer fluid reservoir, or cosmetic damage. Your extended warranty does not pay for any of those things. And since the diagnostic found a non-covered issue, the fee is your responsibility.

This is why understanding your exclusions is just as important as understanding your coverage. Most warranty plans have a long list of things they do not cover — including routine wear and tear items like tires, belts, hoses, brake pads, and wiper blades. Before you take your car in, take five minutes to check whether your issue is likely to be on that excluded list.

How to Avoid Paying Out-of-Pocket for Diagnostic Fees

Read Your Contract Before You Go to the Shop

I cannot stress this enough. Your extended warranty contract is a legal document. Every word in it matters. Before you take your car in, pull out the contract and look for any mention of diagnostic fees, investigative charges, or labor costs.

Look for phrases like “covered diagnostic fees,” “authorized pre-inspection,” or “labor included.” If you see those words, you are in better shape. If you see language like “only the cost of replaced parts is covered” or “diagnostic fees not included,” that is your warning sign.

Some plans include a deductible for each repair visit. Make sure you know what yours is. A $100 deductible means you pay $100 every time you bring the car in, no matter how big or small the repair is.

Call Your Warranty Provider Before the Diagnostic Starts

This is one step that most people skip — and it can save you real money. Before the mechanic starts any diagnostic work, call your warranty company and ask: “If the diagnostic finds a covered problem, will you include the diagnostic fee in the claim?” Get a confirmation number or note the name of the person you spoke with.

This call does two things. First, it tells you what to expect. Second, it puts the warranty company on record that you followed proper procedure. Some plans require you to get authorization before any work begins — if you skip this step, they can legally deny your entire claim, not just the diagnostic fee.

Always ask the repair shop to call your warranty company before starting work, too. Most legitimate shops know this process well and are happy to do it. If a shop refuses to work with your warranty company, that is a red flag worth paying attention to.

Conclusion

So, does your extended warranty cover diagnostics? The answer depends on your specific plan, your warranty provider, and whether the problem found is actually covered by your contract. In general, standard plans often do not cover diagnostics as a standalone fee. But if a covered repair is found and approved, the diagnostic cost is frequently included in the claim.

The best thing you can do right now is read your contract carefully, know what is excluded, and always call your warranty company before work begins. A quick five-minute phone call can save you $150 or more — and a lot of headaches.

Have you ever been surprised by a diagnostic fee on a car that was under warranty? I would love to hear your experience in the comments. It helps other readers know what to watch out for.

Frequently Asked Questions (FAQs)

Q1. Is a diagnostic fee covered under a factory warranty?

Yes, in most cases. If your car is still under the original manufacturer’s warranty — like a 3-year/36,000-mile bumper-to-bumper warranty — and the technician finds a covered defect, the diagnostic fee is typically covered. The manufacturer reimburses the dealer for both the diagnostic time and the repair. However, if no covered problem is found, some dealers may still charge you for the diagnostic work they performed.

Q2. Can a dealership charge me a diagnostic fee if my car is still under warranty?

Yes, they can — but only in certain situations. If your warranty is active and the problem is confirmed as a covered defect, most dealers will not charge you separately for the diagnostic. But if the problem cannot be reproduced, or if the issue falls outside your warranty coverage, the dealer has the right to charge a diagnostic fee. Dealer policies also vary quite a bit, so it is worth calling ahead to ask about their specific approach before bringing your car in.

Q3. What should I do if my extended warranty denies coverage for a diagnostic fee?

First, ask for the denial in writing. Then review your contract carefully to see if diagnostics are mentioned anywhere. If you believe the denial was wrong, you can file a complaint with your state’s consumer protection office or the Federal Trade Commission at reportfraud.ftc.gov. You can also contact your state’s insurance commissioner if the warranty is regulated as an insurance product in your state.

Q4. Do all extended warranty plans cover labor costs?

Not always. Some extended warranty plans cover parts only and do not include labor costs. Labor costs include the technician’s time to remove and replace the broken part — and this can often cost more than the part itself. Before buying an extended warranty, always ask specifically whether labor is included. If the plan only covers parts, your out-of-pocket costs could still be very high even when a claim is approved.

Q5. How can I find out exactly what my extended warranty covers?

The only reliable way is to read your full contract document. Do not rely on what a salesperson told you verbally — those promises are not legally binding unless they are written in the contract. Look for the “Coverage” section and the “Exclusions” section. The exclusions list tells you everything the plan will not cover. If you have trouble understanding the language, call your warranty provider and ask them to explain each section. You can also visit the FTC’s consumer advice page at consumer.ftc.gov/articles/auto-warranties-and-auto-service-contracts for clear, unbiased guidance.

 

We Are Your Warranty Advocates.

Latests Posts

WE DON’T JUST WORK ON CARS, WE FIX THEM!

Auto Repair & Tire Service in Huntsville, AL

At Brian’s Tire & Service we work hard to earn your trust and loyalty. We know how important it is to find a Huntsville car service you can rely on, so your satisfaction is our top priority each and every day.

WE DON’T JUST WORK ON CARS,
WE FIX THEM!

Your Full-Service Automotive Repair Shop

At Brian’s Tire & Service we work hard to earn your trust and loyalty. We know how important it is to find a Huntsville car service you can rely on, so your satisfaction is our top priority each and every day.

Our Automotive Services

Get trusted auto repair and maintenance for your vehicle in Huntsville, AL. From routine care to complex repairs, our team is here to keep your vehicle safe and reliable.

Advanced Diagnostics 1

Advanced Diagnostics

Professional vehicle diagnostics to identify warning lights, performance issues and hard-to-find problems before they become costly repairs.

Maintenance & Repair

Auto Maintenance Services

Comprehensive routine maintenance and repair programs designed to keep your vehicle reliable, safe, efficient, and ready for the road every day.

Suspension Steering maintenance and repair

Suspension & Steering

Keep your vehicle safe and comfortable with professional suspension and steering care for a smoother, safer, and more controlled ride overall.

Engine Maintenance & Repair

Engine Diagnostics & Repair

Identify engine problems early and get reliable repairs to keep your vehicle running smoothly, safely, efficiently, and confidently on the road.

Complete Tire Services

Complete Tire Services

Keep your vehicle safe and road-ready with dependable tire services for improved traction, handling, performance, and long-lasting road safety.

See All Services

From engine repair to tire services, view our complete list of automotive services.

Our Commitment

A Better Automotive Service Experience

At Brian’s Tire & Service, we believe great automotive care goes beyond fixing vehicles, it’s about treating every customer with honesty, respect, and transparency throughout the entire process.

Our team takes the time to explain what your vehicle needs and why, so you can make informed decisions with confidence. No surprises, no pressure, just straightforward service from people who genuinely care.

 

A Better Automotive Service

Comprehensive Tire Services We Offer:

Brian’s Tire & Service is your neighborhood hub for all tire-related needs. Our range of services includes but is not limited to:
Routine Tire Maintenance at Brians Tire and Service

Routine Tire Maintenance

Regular maintenance is key to extending the life of your tires. Our expert team performs thorough inspections and tire rotations every 5,000 miles to promote even wear across all four tires, saving you money and enhancing fuel efficiency.

Prompt Tire Repairs at Brians Tire and Service

Prompt Tire Repairs

Encountered a flat tire or a slow leak? Bring your vehicle to us. With meticulous attention to detail, we’ll uncover the cause of the issue and carry out the necessary repairs, getting you back on the road swiftly and safely.

Precise Wheel Balancing at Brians Tire and Service

Precise Wheel Balancing

Over time, wheel imbalances can lead to unpleasant vibrations, especially at higher speeds. Utilizing state-of-the-art computerized wheel balancing equipment, we rectify these imbalances, ensuring a smooth and comfortable drive.

Rectangle 56 1

Tire Sales and Installation

When it's time for a new set of tires, our vast selection caters to every preference, whether you seek high-performance or budget-friendly options. Our professionals will guide you in choosing the perfect tires and ensure they are installed correctly.

ABOUT US

Brian's Tire & Service in Huntsville

For years Brian’s Tire & Service has been there for the people of Huntsville. We love what we do, and that basic fact fuels our business. We are dedicated to our customers, and that’s why they stick with us—the best auto repair Huntsville has to offer.

Our family of technicians and service staff see their work here as more than a job. It’s their vocation and livelihood. Each member of our team is invested in your satisfaction.

Brian’s Tire & Service was founded on the basic idea that everyone deserves respect. It is our mission to treat each person that comes through our door with dignity and sensitivity. We believe this attention to detail has paid off by providing us with our loyal, friendly family of customers. That’s what makes Brian’s Tire & Service the best car service in Huntsville!

Are you ready to experience the best Huntsville car service available? Please give us a call or book an appointment:

Group 174

Brian Lombardino
Owner

Contact Information

Customer satisfaction is our number one priority. We want to hear from you if you have questions or comments, we’d love to hear from you.

Our Client Reviews

{ "@context": "https://schema.org", "@type": "LocalBusiness", "name": "Brian's Tire & Service", "aggregateRating": { "@type": "AggregateRating", "ratingValue": "4.8", "reviewCount": 605, "bestRating": "5", "worstRating": "1" }, "address": "1024 Putman Dr NW, Huntsville, AL 35816" }

Brian's Buddy Membership

**12 month minimum required per member**

Only $299.95 annually

We offer up to 12 months interest free financing for qualified customers

Wheel

Affiliates & Certification

Car Quest
Technet
OReilly v2
AC Delco red and blue
Be Car Care Aware2
ASA
ASE Certified Logo
BBB
{"prefetch":[{"source":"document","where":{"and":[{"href_matches":"/*"},{"not":{"href_matches":["/wp-*.php","/wp-admin/*","/wp-content/uploads/*","/wp-content/*","/wp-content/plugins/*","/wp-content/themes/brians-warranty-child/*","/wp-content/themes/hello-elementor/*","/*\\?(.+)"]}},{"not":{"selector_matches":"a[rel~=\"nofollow\"]"}},{"not":{"selector_matches":".no-prefetch, .no-prefetch a"}}]},"eagerness":"conservative"}]}
(function() { // Global page view and session tracking for UAEL Modal Popup feature try { // Session tracking: increment if this is a new session // Check if any popup on this page uses current page tracking var hasCurrentPageTracking = false; var currentPagePopups = []; // Check all modal popups on this page for current page tracking if (typeof jQuery !== 'undefined') { jQuery('.uael-modal-parent-wrapper').each(function() { var scope = jQuery(this).data('page-views-scope'); var enabled = jQuery(this).data('page-views-enabled'); var popupId = jQuery(this).attr('id').replace('-overlay', ''); if (enabled === 'yes' && scope === 'current') { hasCurrentPageTracking = true; currentPagePopups.push(popupId); } }); } // Global tracking: ALWAYS increment if ANY popup on the site uses global tracking // Current page tracking: increment per-page counters if (hasCurrentPageTracking && currentPagePopups.length > 0) { var currentUrl = window.location.href; var urlKey = 'uael_page_views_' + btoa(currentUrl).replace(/[^a-zA-Z0-9]/g, '').substring(0, 50); var currentPageViews = parseInt(localStorage.getItem(urlKey) || '0'); currentPageViews++; localStorage.setItem(urlKey, currentPageViews.toString()); // Store URL mapping for each popup for (var i = 0; i < currentPagePopups.length; i++) { var popupUrlKey = 'uael_popup_' + currentPagePopups[i] + '_url_key'; localStorage.setItem(popupUrlKey, urlKey); } } } catch (e) { // Silently fail if localStorage is not available } })();
( () => { const lazyloadRunObserver = () => { const lazyloadBackgrounds = document.querySelectorAll( `.e-con.e-parent:not(.e-lazyloaded)` ); const lazyloadBackgroundObserver = new IntersectionObserver( ( entries ) => { entries.forEach( ( entry ) => { if ( entry.isIntersecting ) { let lazyloadBackground = entry.target; if( lazyloadBackground ) { lazyloadBackground.classList.add( 'e-lazyloaded' ); } lazyloadBackgroundObserver.unobserve( entry.target ); } }); }, { rootMargin: '200px 0px 200px 0px' } ); lazyloadBackgrounds.forEach( ( lazyloadBackground ) => { lazyloadBackgroundObserver.observe( lazyloadBackground ); } ); }; const events = [ 'DOMContentLoaded', 'elementor/lazyload/observe', ]; events.forEach( ( event ) => { document.addEventListener( event, lazyloadRunObserver ); } ); } )(); jQuery.uiBackCompat = true; //# sourceURL=jquery-ui-core-js-before var uael_particles_script = {"uael_particles_url":"https://brianstireandservice.com/wp-content/plugins/ultimate-elementor/assets/min-js/uael-particles.min.js","particles_url":"https://brianstireandservice.com/wp-content/plugins/ultimate-elementor/assets/lib/particles/particles.min.js","snowflakes_image":"https://brianstireandservice.com/wp-content/plugins/ultimate-elementor/assets/img/snowflake.svg","gift":"https://brianstireandservice.com/wp-content/plugins/ultimate-elementor/assets/img/gift.png","tree":"https://brianstireandservice.com/wp-content/plugins/ultimate-elementor/assets/img/tree.png","skull":"https://brianstireandservice.com/wp-content/plugins/ultimate-elementor/assets/img/skull.png","ghost":"https://brianstireandservice.com/wp-content/plugins/ultimate-elementor/assets/img/ghost.png","moon":"https://brianstireandservice.com/wp-content/plugins/ultimate-elementor/assets/img/moon.png","bat":"https://brianstireandservice.com/wp-content/plugins/ultimate-elementor/assets/img/bat.png","pumpkin":"https://brianstireandservice.com/wp-content/plugins/ultimate-elementor/assets/img/pumpkin.png"}; //# sourceURL=elementor-frontend-js-extra var elementorFrontendConfig = {"environmentMode":{"edit":false,"wpPreview":false,"isScriptDebug":false},"i18n":{"shareOnFacebook":"Share on Facebook","shareOnX":"Share on X","pinIt":"Pin it","download":"Download","downloadImage":"Download image","fullscreen":"Fullscreen","zoom":"Zoom","share":"Share","playVideo":"Play Video","previous":"Previous","next":"Next","close":"Close","a11yCarouselPrevSlideMessage":"Previous slide","a11yCarouselNextSlideMessage":"Next slide","a11yCarouselFirstSlideMessage":"This is the first slide","a11yCarouselLastSlideMessage":"This is the last slide","a11yCarouselPaginationBulletMessage":"Go to slide"},"is_rtl":false,"breakpoints":{"xs":0,"sm":480,"md":768,"lg":1025,"xl":1440,"xxl":1600},"responsive":{"breakpoints":{"mobile":{"label":"Mobile Portrait","value":767,"default_value":767,"direction":"max","is_enabled":true},"mobile_extra":{"label":"Mobile Landscape","value":880,"default_value":880,"direction":"max","is_enabled":false},"tablet":{"label":"Tablet Portrait","value":1024,"default_value":1024,"direction":"max","is_enabled":true},"tablet_extra":{"label":"Tablet Landscape","value":1200,"default_value":1200,"direction":"max","is_enabled":false},"laptop":{"label":"Laptop","value":1366,"default_value":1366,"direction":"max","is_enabled":false},"widescreen":{"label":"Widescreen","value":2400,"default_value":2400,"direction":"min","is_enabled":false}},"hasCustomBreakpoints":false},"version":"4.3.6","is_static":false,"experimentalFeatures":{"additional_custom_breakpoints":true,"container":true,"theme_builder_v2":true,"hello-theme-header-footer":true,"nested-elements":true,"import-export-customization":true,"e_pro_atomic_form":true,"mega-menu":true,"e_pro_variables":true,"e_pro_interactions":true},"urls":{"assets":"https:\/\/brianstireandservice.com\/wp-content\/plugins\/elementor\/assets\/","ajaxurl":"https:\/\/brianstireandservice.com\/wp-admin\/admin-ajax.php","uploadUrl":"https:\/\/brianstireandservice.com\/wp-content\/uploads"},"nonces":{"floatingButtonsClickTracking":"cce75da8da","atomicFormsSendForm":"d3ea069d70"},"swiperClass":"swiper","settings":{"page":[],"editorPreferences":[]},"kit":{"active_breakpoints":["viewport_mobile","viewport_tablet"],"global_image_lightbox":"yes","lightbox_enable_counter":"yes","lightbox_enable_fullscreen":"yes","lightbox_enable_zoom":"yes","lightbox_enable_share":"yes","lightbox_title_src":"title","lightbox_description_src":"description","hello_header_logo_type":"logo","hello_header_menu_layout":"horizontal","hello_footer_logo_type":"logo"},"post":{"id":24,"title":"Auto%20Repair%20%26%20Tires%20In%20Huntsville%2C%20AL%20%7C%20Brian%27s%20Tire%20%26%20Auto","excerpt":"","featuredImage":"https:\/\/brianstireandservice.com\/wp-content\/uploads\/2023\/11\/brians-Tire-Service-Home-1024x536.jpg"}}; //# sourceURL=elementor-frontend-js-before window.scope_array = []; window.backend = 0; jQuery.cachedScript = function( url, options ) { // Allow user to set any option except for dataType, cache, and url. options = jQuery.extend( options || {}, { dataType: "script", cache: true, url: url }); // Return the jqXHR object so we can chain callbacks. return jQuery.ajax( options ); }; jQuery( window ).on( "elementor/frontend/init", function() { elementorFrontend.hooks.addAction( "frontend/element_ready/global", function( $scope, $ ){ if ( "undefined" == typeof $scope ) { return; } if ( $scope.hasClass( "uael-particle-yes" ) ) { window.scope_array.push( $scope ); $scope.find(".uael-particle-wrapper").addClass("js-is-enabled"); }else{ return; } if(elementorFrontend.isEditMode() && $scope.find(".uael-particle-wrapper").hasClass("js-is-enabled") && window.backend == 0 ){ var uael_url = uael_particles_script.uael_particles_url; jQuery.cachedScript( uael_url ); window.backend = 1; }else if(elementorFrontend.isEditMode()){ var uael_url = uael_particles_script.uael_particles_url; jQuery.cachedScript( uael_url ).done(function(){ var flag = true; }); } }); }); // Added both `document` and `window` event listeners to address issues where some users faced problems with the `document` event not triggering as expected. // Define cachedScript globally to avoid redefining it. jQuery.cachedScript = function(url, options) { options = jQuery.extend(options || {}, { dataType: "script", cache: true, url: url }); return jQuery.ajax(options); // Return the jqXHR object so we can chain callbacks }; let uael_particle_loaded = false; //flag to prevent multiple script loads. jQuery( document ).on( "ready elementor/popup/show", () => { loadParticleScript(); }); jQuery( window ).one( "elementor/frontend/init", () => { if (!uael_particle_loaded) { loadParticleScript(); } }); function loadParticleScript(){ // Use jQuery to check for the presence of the element if (jQuery(".uael-particle-yes").length < 1) { return; } uael_particle_loaded = true; var uael_url = uael_particles_script.uael_particles_url; // Call the cachedScript function jQuery.cachedScript(uael_url); } //# sourceURL=elementor-frontend-js-after var mdpReadablerOptions = {"ajaxurl":"https://brianstireandservice.com/wp-admin/admin-ajax.php","nonce":"cebc04f094","pluginURL":"https://brianstireandservice.com/wp-content/plugins/readabler/","postID":"24","postType":"page","translation":{"voiceGuide":"","voiceRecognitionStart":"Say a command...","voiceRecognitionEnd":"Voice recognition has stopped","voiceRecognitionWait":"Wait...","voiceRecognitionLegend":"Voice recognition","voiceRecognitionCommands":"Voice commands","voiceRecognitionHistory":"History","voiceRecognitionClose":"Close and stop voice navigation","voiceRecognitionErrorNoVoice":"Voice recognition has stopped, no voice detected. Click the button to restart recognition.","voiceRecognitionErrorNoNetwork":"Network error. Check is you online and try again.","voiceRecognitionErrorNoMic":"No microphone. Check is your microphone connected and try again.","voiceRecognitionErrorNoPermission":"Permission denied. Check is your microphone connected and try again.","voiceRecognitionErrorNotAllowed":"Microphone access denied. Check is your microphone connected and try again.","voiceRecognitionErrorUnknown":"Voice recognition error. Try again.","voiceRecognitionNumbers":["zero","one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen","twenty","twenty one","twenty two","twenty three","twenty four","twenty five","twenty six","twenty seven","twenty eight","twenty nine","thirty","thirty one","thirty two","thirty three","thirty four","thirty five","thirty six","thirty seven","thirty eight","thirty nine","forty","forty one","forty two","forty three","forty four","forty five","forty six","forty seven","forty eight","forty nine","fifty","fifty one","fifty two","fifty three","fifty four","fifty five","fifty six","fifty seven","fifty eight","fifty nine","sixty","sixty one","sixty two","sixty three","sixty four","sixty five","sixty six","sixty seven","sixty eight","sixty nine","seventy","seventy one","seventy two","seventy three","seventy four","seventy five","seventy six","seventy seven","seventy eight","seventy nine","eighty","eighty one","eighty two","eighty three","eighty four","eighty five","eighty six","eighty seven","eighty eight","eighty nine","ninety","ninety one","ninety two","ninety three","ninety four","ninety five","ninety six","ninety seven","ninety eight","ninety nine","one hundred","one hundred one","one hundred two","one hundred three","one hundred four","one hundred five","one hundred six","one hundred seven","one hundred eight","one hundred nine","one hundred ten","one hundred eleven","one hundred twelve","one hundred thirteen","one hundred fourteen","one hundred fifteen","one hundred sixteen","one hundred seventeen","one hundred eighteen","one hundred nineteen","one hundred twenty","one hundred twenty one","one hundred twenty two","one hundred twenty three","one hundred twenty four","one hundred twenty five","one hundred twenty six","one hundred twenty seven","one hundred twenty eight","one hundred twenty nine","one hundred thirty","one hundred thirty one","one hundred thirty two","one hundred thirty three","one hundred thirty four","one hundred thirty five","one hundred thirty six","one hundred thirty seven","one hundred thirty eight","one hundred thirty nine","one hundred forty","one hundred forty one","one hundred forty two","one hundred forty three","one hundred forty four","one hundred forty five","one hundred forty six","one hundred forty seven","one hundred forty eight","one hundred forty nine","one hundred fifty","one hundred fifty one","one hundred fifty two","one hundred fifty three","one hundred fifty four","one hundred fifty five","one hundred fifty six","one hundred fifty seven","one hundred fifty eight","one hundred fifty nine","one hundred sixty","one hundred sixty one","one hundred sixty two","one hundred sixty three","one hundred sixty four","one hundred sixty five","one hundred sixty six","one hundred sixty seven","one hundred sixty eight","one hundred sixty nine","one hundred seventy","one hundred seventy one","one hundred seventy two","one hundred seventy three","one hundred seventy four","one hundred seventy five","one hundred seventy six","one hundred seventy seven","one hundred seventy eight","one hundred seventy nine","one hundred eighty","one hundred eighty one","one hundred eighty two","one hundred eighty three","one hundred eighty four","one hundred eighty five","one hundred eighty six","one hundred eighty seven","one hundred eighty eight","one hundred eighty nine","one hundred ninety","one hundred ninety one","one hundred ninety two","one hundred ninety three","one hundred ninety four","one hundred ninety five","one hundred ninety six","one hundred ninety seven","one hundred ninety eight","one hundred ninety nine","two hundred"]},"popupPosition":"center","popupOverlay":"","buttons":{"resetButton":true,"hideButton":true},"headers":{"accessibilityProfiles":true,"onlineDictionary":true,"readableExperience":true,"visuallyPleasing":true,"visualAssistance":true,"easyOrientation":true},"onlineDictionary":"1","language":"auto","profileEpilepsy":"1","profileVisuallyImpaired":"1","profileCognitiveDisability":"1","profileAdhdFriendly":"","profileBlindUsers":"1","contentScaling":"1","readableFont":"1","dyslexiaFont":"1","highlightTitles":"1","highlightLinks":"1","textMagnifier":"1","fontSizing":"1","lineHeight":"1","letterSpacing":"1","alignCenter":"1","alignLeft":"1","alignRight":"1","darkContrast":"1","lightContrast":"1","monochrome":"1","highSaturation":"1","highContrast":"1","lowSaturation":"1","textColors":"1","titleColors":"1","backgroundColors":"1","muteSounds":"1","hideImages":"1","hideEmoji":"1","virtualKeyboard":"1","readingGuide":"1","cognitiveReading":"1","cognitiveReadingFocus":"","cognitiveReadingFixation":"normal","usefulLinks":"1","stopAnimations":"1","readingMask":"1","highlightHover":"1","highlightFocus":"1","bigBlackCursor":"1","bigWhiteCursor":"1","textToSpeech":"","voiceNavigation":{"help":["help","help_me","show_commands"],"hide_help":["hide_help","hide_commands","hide_commands_list"],"scroll_down":["scroll_down","down","page_down"],"scroll_up":["scroll_up","up","page_up"],"go_to_top":["go_to_top","top","page_top"],"go_to_bottom":["go_to_bottom","bottom","page_bottom"],"tab":["tab","next","next_tab"],"tab_back":["tab_back","previous","previous_tab"],"show_numbers":["show_numbers","display_numbers","enable_numbers"],"number":["click","press","open"],"hide_numbers":["hide_numbers","disable_numbers","remove_numbers"],"clear_input":["clear_input","clear","remove"],"enter":["enter","submit","ok"],"reload":["reload","refresh","update"],"stop":["stop","cancel","stop_listening"],"exit":["exit","quit","close"]},"keyboardNavigation":"1","startConfig":"","startContentScaling":"0","startFontSizing":"0","startLineHeight":"0","startLetterSpacing":"0","ignoreSavedConfig":"off","showOpenButton":"1","buttonPosition":"right-center","buttonCaption":"","buttonIcon":"_readabler/readabler.svg","buttonIconPosition":"before","buttonSize":"24","buttonMargin":"10","buttonPadding":"20","buttonBorderRadius":"50","buttonColor":"rgba(255, 255, 255, 1)","buttonColorHover":"rgba(33, 111, 243, 1)","buttonBgcolor":"rgba(33, 111, 243, 1)","buttonBgcolorHover":"rgba(255, 255, 255, 1)","buttonEntranceTimeout":"0","buttonEntranceAnimation":"fade","buttonHoverAnimation":"none","buttonShowAfterScrolling":{"desktop":"0","mobile":"0"},"popupOverlayColor":"rgba(2, 83, 238, 1)","popupBackgroundColor":"rgba(255, 255, 255, 1)","popupKeyColor":"rgba(33, 111, 243, 1)","popupBorderRadius":"20","popupAnimation":"fade","popupScroll":"","closeAnywhere":"","popupDraggable":"1","highlightP":"","readAlt":"","hotKeyOpenInterface":"Alt+9","saveConfig":"on","analytics":"off","analyticsSendInterval":"2","analyticsGDPR":"off","statementType":"inline","LEARN_MORE_IN_WIKIPEDIA":"Learn more in Wikipedia","DEFAULT":"Default","HOME":"Home","HIDE_ACCESSIBILITY_INTERFACE":"If you choose to hide the accessibility interface, you won't be able to see it anymore, unless you clear clear cookies for this site. Are you sure that you wish to hide the interface?","readingMaskHeight":"100","virtualKeyboardLayout":["english"],"virtualKeyboardLayouts":{"en":"{\"default\":[\"` 1 2 3 4 5 6 7 8 9 0 - = {bksp}\",\"{tab} q w e r t y u i o p [ ] \\\\\",\"{lock} a s d f g h j k l ; ' {enter}\",\"{shift} z x c v b n m , . \\/ {shift}\",\".com @ {space}\"],\"shift\":[\"~ ! @ # $ % ^ & * ( ) _ + {bksp}\",\"{tab} Q W E R T Y U I O P { } |\",\"{lock} A S D F G H J K L : \\\" {enter}\",\"{shift} Z X C V B N M \u003C \u003E ? {shift}\",\".com @ {space}\"],\"lang\":{\"en\":\"English\"}}"},"hotKeyMenu":"","hotKeyHeadings":"","hotKeyForms":"","hotKeyButtons":"","hotKeyGraphics":"","highlightFocusColor":"#639af9","voiceNavigationAliases":{"help":"Help","help_me":"Help me","show_commands":"Show commands","what_can_i_say":"What can I say","what_can_i_do":"What can I do","what_can_you_do":"What can you do","available_commands":"Available commands","commands_list":"Commands list","hide_help":"Hide help","hide_commands":"Hide commands","hide_commands_list":"Hide commands list","hide_available_commands":"Hide available commands","collapse_commands":"Collapse commands","scroll_down":"Scroll down","down":"Down","page_down":"Page Down","go_down":"Go down","scroll_up":"Scroll up","up":"Up","page_up":"Page Up","go_up":"Go up","go_to_top":"Go to top","top":"Top","page_top":"Page Top","go_to_start":"Go to start","scroll_to_top":"Scroll to top","go_to_bottom":"Go to bottom","bottom":"Bottom","page_bottom":"Page Bottom","go_to_end":"Go to end","scroll_to_bottom":"Scroll to bottom","tab":"Tab","next":"Next","next_tab":"Next Tab","go_to_next":"Go to next","go_to_next_tab":"Go to next tab","tab_back":"Tab back","previous":"Previous","previous_tab":"Previous Tab","go_to_previous":"Go to previous","go_to_previous_tab":"Go to previous tab","show_numbers":"Show numbers","display_numbers":"Display numbers","enable_numbers":"Enable numbers","navigation_numbers":"Navigation numbers","mark_links":"Mark links","number_links":"Number links","click":"Click","press":"Press","open":"Open","go_to":"Go to","go":"Go","select":"Select","hide_numbers":"Hide numbers","disable_numbers":"Disable numbers","remove_numbers":"Remove numbers","hide_mark_links":"Mark links","hide_number_links":"Number links","clear_input":"Clear input","clear":"Clear","remove":"Remove","delete":"Delete","clear_text":"Clear text","clear_search":"Clear search","enter":"Enter","submit":"Submit","ok":"Ok","confirm":"Confirm","accept":"Accept","return":"Return","yes":"Yes","reload":"Reload","refresh":"Refresh","update":"Update","refresh_page":"Refresh page","reload_page":"Reload page","reload_website":"Reload website","refresh_website":"Refresh website","stop":"Stop","cancel":"Cancel","stop_listening":"Stop listening","cancel_listening":"Cancel listening","stop_recording":"Stop recording","stop_voice_navigation":"Stop voice navigation","abort":"Abort","exit":"Exit","quit":"Quit","close":"Close","close_window":"Close window","close_navigation":"Close navigation","close_panel":"Close panel","number":"Number ... "},"voiceNavigationDescription":{"help":"Display a list of available voice commands","hide_help":"Hide a list of available voice commands","scroll_down":"Scroll page down 200 px","scroll_up":"Scroll page down 200 px","go_to_top":"Scroll page to top","go_to_bottom":"Scroll page to bottom","tab":"Move to next interactive element","tab_back":"Move to previous interactive element","show_numbers":"Show numbers for interactive elements","number":"Click on element number...","hide_numbers":"Hide numbers for interactive elements","clear_input":"Clear selected text field","enter":"Click on the selected element","reload":"Reload page","stop":"Stop speech recognition","exit":"Disable voice navigation mode"},"voiceNavigationRerun":"off","scrollDownValue":"200","scrollUpValue":"-200","scrollLeftValue":"-200","scrollRightValue":"200","voiceNavigationVoiceGraph":"on","voiceNavigationInterimResults":"on","voiceNavigationFeedback":"on","voiceNavigationFeedbackOk":["OK","Yes","Done"],"voiceNavigationFeedbackStart":["Start listening","Begin listening","Listening"],"voiceNavigationFeedbackEnd":["End listening","Stop listening","Finish listening"]}; //# sourceURL=mdp-readabler-js-extra For full functionality of this site it is necessary to enable JavaScript. window._googlesitekit = window._googlesitekit || {}; window._googlesitekit.contentEvents = {"postID":24,"isReadableSinglePost":false,"hasVimeoEmbed":false,"wordCount":0,"estimatedReadTimeSeconds":0,"isLastPageOfMultiPagePost":false,"readTimeThresholdPercent":85,"minimumReadTimeSeconds":5}; //# sourceURL=googlesitekit-events-provider-content-events-js-before window.gtranslateSettings = /* document.write */ window.gtranslateSettings || {};window.gtranslateSettings['81955390'] = {"default_language":"en","languages":["en","es"],"url_structure":"none","native_language_names":1,"detect_browser_language":1,"flag_style":"2d","wrapper_selector":"#gt-wrapper-81955390","alt_flags":{"en":"usa"},"float_switcher_open_direction":"top","switcher_horizontal_position":"left","switcher_vertical_position":"bottom","flags_location":"\/wp-content\/plugins\/gtranslate\/flags\/"}; //# sourceURL=gt_widget_script_81955390-js-before wp.i18n.setLocaleData( { 'text direction\u0004ltr': [ 'ltr' ] } ); //# sourceURL=wp-i18n-js-after var ElementorProFrontendConfig = {"ajaxurl":"https:\/\/brianstireandservice.com\/wp-admin\/admin-ajax.php","nonce":"ef95be8132","urls":{"assets":"https:\/\/brianstireandservice.com\/wp-content\/plugins\/elementor-pro\/assets\/","rest":"https:\/\/brianstireandservice.com\/wp-json\/"},"settings":{"lazy_load_background_images":true},"popup":{"hasPopUps":true},"shareButtonsNetworks":{"facebook":{"title":"Facebook","has_counter":true},"twitter":{"title":"Twitter"},"linkedin":{"title":"LinkedIn","has_counter":true},"pinterest":{"title":"Pinterest","has_counter":true},"reddit":{"title":"Reddit","has_counter":true},"vk":{"title":"VK","has_counter":true},"odnoklassniki":{"title":"OK","has_counter":true},"tumblr":{"title":"Tumblr"},"digg":{"title":"Digg"},"skype":{"title":"Skype"},"stumbleupon":{"title":"StumbleUpon","has_counter":true},"mix":{"title":"Mix"},"telegram":{"title":"Telegram"},"pocket":{"title":"Pocket","has_counter":true},"xing":{"title":"XING","has_counter":true},"whatsapp":{"title":"WhatsApp"},"email":{"title":"Email"},"print":{"title":"Print"},"x-twitter":{"title":"X"},"threads":{"title":"Threads"}},"facebook_sdk":{"lang":"en_US","app_id":""},"lottie":{"defaultAnimationUrl":"https:\/\/brianstireandservice.com\/wp-content\/plugins\/elementor-pro\/modules\/lottie\/assets\/animations\/default.json"}}; //# sourceURL=elementor-pro-frontend-js-before {"baseUrl":"https://s.w.org/images/core/emoji/17.0.2/72x72/","ext":".png","svgUrl":"https://s.w.org/images/core/emoji/17.0.2/svg/","svgExt":".svg","source":{"concatemoji":"https://brianstireandservice.com/wp-includes/js/wp-emoji-release.min.js?ver=7.1.4"}} /*! This file is auto-generated */ var e="script#wp-emoji-settings",t=document.querySelector(e);if(!(t instanceof HTMLScriptElement))throw new Error("Element missing: "+e);const r=JSON.parse(t.text),s=(window._wpemojiSettings=r,"wpEmojiSettingsSupports"),o=["flag","emoji"];function i(e){try{var t={supportTests:e,timestamp:(new Date).valueOf()};sessionStorage.setItem(s,JSON.stringify(t))}catch(e){}}function c(e,t,n){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);t=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data);e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(n,0,0);const r=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data);return t.every((e,t)=>e===r[t])}function p(e,t){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);var n=e.getImageData(16,16,1,1);for(let e=0;e{o[e]=t(s,e,n,r)}),o}function a(e){var t=document.createElement("script");t.src=e,t.defer=!0,document.head.appendChild(t)}r.supports={everything:!0,everythingExceptFlag:!0},new Promise(t=>{let n=function(){try{var e=JSON.parse(sessionStorage.getItem(s));if("object"==typeof e&&"number"==typeof e.timestamp&&(new Date).valueOf(){i(n=e.data),a.terminate(),t(n)})}catch(e){}i(n=f(o,u,c,p))}t(n)}).then(e=>{for(const n in e)r.supports[n]=e[n],r.supports.everything=r.supports.everything&&r.supports[n],"flag"!==n&&(r.supports.everythingExceptFlag=r.supports.everythingExceptFlag&&r.supports[n]);var t;r.supports.everythingExceptFlag=r.supports.everythingExceptFlag&&!r.supports.flag,r.supports.everything||((t=r.source||{}).concatemoji?a(t.concatemoji):t.wpemoji&&t.twemoji&&(a(t.twemoji),a(t.wpemoji)))}); //# sourceURL=https://brianstireandservice.com/wp-includes/js/wp-emoji-loader.min.js /** * Leadflow Collector — client-side tracking engine. * * Auto-detects every on the page. No manual configuration of * individual forms is required. * * For each form it: * 1. Starts a timer on the first field interaction. * 2. On submit, compiles a JSON payload covering the four pillars: * - usage_data (page url, title, referrer, viewport) * - behavior_metrics (seconds spent filling the form) * - lead_payload (form id/class + every field name -> value) * - lead_email (best-guess email, promoted to top level) * 3. Sends the payload via fetch() WITHOUT blocking or preventing the * native submit — the host site's form behaves exactly as before. * * https://inceptial.team/SEO-Dashboard/wp-json/hub-leads/v1/capture, 5U50fReBFK3oJEP1pCgWeODjtthGfeALafZYt3V2, https://brianstireandservice.com/wp-admin/admin-ajax.php, and a623cc6a42 are replaced * server-side (PHP) before this file is ever printed to the page. */ ( function () { 'use strict'; var HUB_ENDPOINT = 'https://inceptial.team/SEO-Dashboard/wp-json/hub-leads/v1/capture'; var HUB_API_KEY = '5U50fReBFK3oJEP1pCgWeODjtthGfeALafZYt3V2'; var HUB_LOG_URL = 'https://brianstireandservice.com/wp-admin/admin-ajax.php'; var HUB_LOG_NONCE = 'a623cc6a42'; // URL of the Collector's store-sync-key REST endpoint. Empty string once // the sync_key has been persisted server-side (PHP outputs '' at that point). var HUB_STORE_SYNC_KEY_URL = ''; // Click Trackers — phone/email/location/anything else defined on the // Collector's settings page. Substituted server-side as a raw JSON // array literal (valid JSON is valid JS), NOT a quoted string — a // tracker label containing an apostrophe (e.g. "Book It's Time") // would otherwise break out of a quoted string. See attachClickTrackers(). var CLICK_TRACKERS = [{"id":"call","label":"Call","href_prefixes":["tel:"],"href_contains":[],"keywords":["call 256-704-8473"],"selector":"","text_pattern":"phone"},{"id":"email-click","label":"Email Click","href_prefixes":["mailto:"],"href_contains":[],"keywords":["info@brians.tires"],"selector":"","text_pattern":"email"},{"id":"location-click","label":"Location Click","href_prefixes":[],"href_contains":[],"keywords":["1024 putman dr nw","huntsville","al 35816","united states"],"selector":"","text_pattern":""},{"id":"book-an-appointment","label":"book an appointment","href_prefixes":[],"href_contains":[],"keywords":["book an appointment"],"selector":"","text_pattern":""},{"id":"call-2","label":"Call","href_prefixes":["tel:"],"href_contains":[],"keywords":["call: 256-704-8473"],"selector":"","text_pattern":"phone"}]; if ( ! Array.isArray( CLICK_TRACKERS ) ) { CLICK_TRACKERS = []; } // Page Trackers — fire a page_view event when the current URL matches // one of the configured tracked pages. Substituted server-side as a // raw JSON array literal. var PAGE_TRACKERS = [{"id":"car-engine","label":"car engine","page_url":"https:\/\/brianstireandservice.com\/auto-engine-repair\/","match_type":"contains","href_prefixes":[],"href_contains":[],"keywords":["learn more"],"selector":"","text_pattern":""}]; if ( ! Array.isArray( PAGE_TRACKERS ) ) { PAGE_TRACKERS = []; } // Belt-and-suspenders: the PHP injector already guards this, but never // run a half-configured tracker. if ( ! HUB_ENDPOINT || ! HUB_API_KEY ) { return; } /** * Cookie-based visitor ID — persists across sessions so returning * visitors can be identified even after closing and reopening the browser. * A new random ID is assigned on first visit (or after cookie clearance). * Expires after 2 years. Never contains personal data — just a random hex string. */ function getVisitorId() { var COOKIE_NAME = 'hub_vid'; var COOKIE_DAYS = 730; // 2 years // Try to read existing cookie. var existing = ''; var cookies = document.cookie ? document.cookie.split( ';' ) : []; for ( var i = 0; i < cookies.length; i++ ) { var parts = cookies[ i ].trim().split( '=' ); if ( parts[ 0 ] === COOKIE_NAME ) { existing = decodeURIComponent( parts[ 1 ] || '' ); break; } } if ( existing ) { return existing; } // Generate a new random ID: 16 hex chars. var id = ''; var chars = '0123456789abcdef'; for ( var j = 0; j < 16; j++ ) { id += chars[ Math.floor( Math.random() * 16 ) ]; } // Persist in cookie. var expires = new Date(); expires.setTime( expires.getTime() + COOKIE_DAYS * 24 * 60 * 60 * 1000 ); document.cookie = COOKIE_NAME + '=' + encodeURIComponent( id ) + '; expires=' + expires.toUTCString() + '; path=/' + '; SameSite=Lax'; return id; } // Resolve visitor ID once at page load and reuse across all payloads. var HUB_VISITOR_ID = getVisitorId(); /** * Lightweight User-Agent parse — device type, OS, browser. Good enough * for lead-gen reporting; not meant to rival a full UA-parsing library. * Order matters (e.g. iPad must be checked before "Mac" substring * traps, Edge before Chrome, etc.). */ function getDeviceInfo() { var ua = navigator.userAgent || ''; var deviceType = 'Desktop'; if ( /iPad/i.test( ua ) || ( /Macintosh/i.test( ua ) && 'ontouchend' in document ) ) { deviceType = 'Tablet'; } else if ( /Android/i.test( ua ) && ! /Mobile/i.test( ua ) ) { deviceType = 'Tablet'; } else if ( /Mobi|iPhone|Android/i.test( ua ) ) { deviceType = 'Mobile'; } var os = 'Unknown'; if ( /iPhone|iPad|iPod/i.test( ua ) ) { os = 'iOS'; } else if ( /Android/i.test( ua ) ) { os = 'Android'; } else if ( /Windows/i.test( ua ) ) { os = 'Windows'; } else if ( /Macintosh|Mac OS X/i.test( ua ) ) { os = 'macOS'; } else if ( /CrOS/i.test( ua ) ) { os = 'ChromeOS'; } else if ( /Linux/i.test( ua ) ) { os = 'Linux'; } var browser = 'Unknown'; if ( /Edg\// .test( ua ) ) { browser = 'Edge'; } else if ( /OPR\/|Opera/.test( ua ) ) { browser = 'Opera'; } else if ( /Firefox\//.test( ua ) ) { browser = 'Firefox'; } else if ( /CriOS\//.test( ua ) ) { browser = 'Chrome'; } else if ( /Chrome\//.test( ua ) && ! /Chromium\//.test( ua ) ) { browser = 'Chrome'; } else if ( /Safari\//.test( ua ) && /Version\//.test( ua ) ) { browser = 'Safari'; } return { type: deviceType, os: os, browser: browser, user_agent: ua.slice( 0, 300 ) }; } // Shared de-dupe registry between the native-submit-event path and the // network-level path (see patchFetch/patchXhr below), so a builder // that fires BOTH signals for the same real submission — e.g. no // CAPTCHA involved, so the native submit event works AND we also see // the underlying AJAX call — doesn't create two leads for one // submission. Keyed by form_type rather than a specific form // instance/id, since the network path only knows the builder, not // which exact on the page fired it. var recentlySent = {}; var DEDUPE_WINDOW_MS = 4000; function shouldSendForKey( key ) { var now = Date.now(); var last = recentlySent[ key ] || 0; if ( now - last < DEDUPE_WINDOW_MS ) { return false; } recentlySent[ key ] = now; return true; } /** * Fire-and-forget report to this site's OWN Activity Log (not the Hub). * Records metadata only — never field values or the email itself — so * the person managing this client site can see, locally, whether * submissions are making it out. Failures here are swallowed; a logging * hiccup must never affect the real lead delivery above. */ function logEvent( fields ) { if ( ! HUB_LOG_URL || ! HUB_LOG_NONCE ) { return; } try { var params = new URLSearchParams(); params.set( 'action', 'hub_collector_log_event' ); params.set( 'nonce', HUB_LOG_NONCE ); Object.keys( fields ).forEach( function ( key ) { var value = fields[ key ]; params.set( key, null === value || undefined === value ? '' : String( value ) ); } ); fetch( HUB_LOG_URL, { method: 'POST', keepalive: true, headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: params.toString() } ).catch( function () {} ); } catch ( e ) { // no-op } } // Per-form interaction state (when the visitor first touched a field). var formState = new WeakMap(); /** * Form-builder signature registry — Layer 1 of the detection system. * Every signature below was verified against each plugin's actual * rendered markup (official docs / source / GitHub), not guessed. * Checked top-to-bottom, first match wins. Unmatched forms fall through * to 'other' — they're still tracked normally, just unlabeled. * * Each `test` receives the element itself. `form.closest()` also * checks the form itself, so signatures work whether the matching class * lives on the tag or on a wrapping container around it. */ var FORM_BUILDER_SIGNATURES = [ { key: 'contact_form_7', test: function ( form ) { return form.classList.contains( 'wpcf7-form' ); } }, { key: 'wpforms', test: function ( form ) { return form.classList.contains( 'wpforms-form' ) || /^wpforms-form-/.test( form.id || '' ); } }, { key: 'gravity_forms', test: function ( form ) { return /^gform_\d+$/.test( form.id || '' ) || !! form.closest( '.gform_wrapper' ); } }, { key: 'ninja_forms', test: function ( form ) { return form.classList.contains( 'nf-form-layout' ) || !! form.closest( '.nf-form-cont' ); } }, { key: 'formidable', test: function ( form ) { return form.classList.contains( 'frm-show-form' ) || !! form.closest( '.frm_forms' ); } }, { key: 'fluent_forms', test: function ( form ) { return form.classList.contains( 'frm-fluent-form' ); } }, { key: 'elementor', // Elementor Pro submits via AJAX — the network watcher (fetch/XHR // patch) already captures the real submission. Skipping the DOM // submit event here prevents a duplicate lead. networkOnly: true, test: function ( form ) { return form.classList.contains( 'elementor-form' ); } }, { key: 'forminator', test: function ( form ) { return form.classList.contains( 'forminator-custom-form' ) || /^forminator-module-/.test( form.id || '' ); } }, { key: 'caldera_forms', test: function ( form ) { return form.classList.contains( 'caldera-forms-form' ) || /^caldera_forms_form/.test( form.id || '' ); } }, { key: 'divi', test: function ( form ) { return form.classList.contains( 'et_pb_contact_form' ); } }, { key: 'woocommerce_checkout', test: function ( form ) { return form.classList.contains( 'woocommerce-checkout' ); } }, { key: 'jetpack', test: function ( form ) { return !! form.closest( '.contact-form-container' ) || !! form.closest( '.wp-block-jetpack-contact-form' ); } }, { key: 'hubspot', test: function ( form ) { return form.classList.contains( 'hs-form' ); } }, { key: 'mailchimp', test: function ( form ) { return 'mc-embedded-subscribe-form' === form.id; } } ]; /** * Returns a signature key ('wpforms', 'elementor', etc.) or 'other' if * nothing matched. A single broken test must never crash detection for * the rest of the registry or for the form's own submission. */ function detectFormBuilder( form ) { for ( var i = 0; i < FORM_BUILDER_SIGNATURES.length; i++ ) { try { if ( FORM_BUILDER_SIGNATURES[ i ].test( form ) ) { return FORM_BUILDER_SIGNATURES[ i ].key; } } catch ( e ) { // Skip this signature, keep checking the rest. } } return 'other'; } /** * Returns true for builders that submit via AJAX and are already captured * by the network watcher. The DOM submit listener skips these to prevent * sending a duplicate lead. */ function isNetworkOnlyBuilder( form ) { for ( var i = 0; i < FORM_BUILDER_SIGNATURES.length; i++ ) { try { if ( FORM_BUILDER_SIGNATURES[ i ].networkOnly && FORM_BUILDER_SIGNATURES[ i ].test( form ) ) { return true; } } catch ( e ) {} } return false; } /** * Forms that are never leads: WordPress's own login form, the default * comment form, and search forms. Excluded by default so they never * pollute lead data — these never get a listener attached at all. */ function isExcludedForm( form ) { if ( 'loginform' === form.id || 'commentform' === form.id ) { return true; } if ( 'search' === ( form.getAttribute( 'role' ) || '' ).toLowerCase() ) { return true; } if ( form.classList.contains( 'search-form' ) ) { return true; } return false; } function cssEscape( value ) { if ( window.CSS && typeof window.CSS.escape === 'function' ) { return window.CSS.escape( value ); } return String( value ).replace( /([^\w-])/g, '\\$1' ); } /** * Best-effort human-readable label for a field: