WordPress Maintenance | Senior Fixes Without Retainers

WordPress Maintenance | Senior Fixes Without Retainers
        
        
    
    
    
    
    
    
    
    
    
    
    


































    
{
    "@context": "https://schema.org",
    "@graph": [
        {
            "@type": "Organization",
            "@id": "https://funkpd.com/#org",
            "name": "FunkPd",
            "alternateName": [
                "FunkProductions",
                "Funk Productions"
            ],
            "url": "https://funkpd.com/",
            "foundingDate": "2017",
            "founder": {
                "@type": "Person",
                "@id": "https://funkpd.com/nolan/#person",
                "name": "Nolan Phelps",
                "url": "https://funkpd.com/nolan/"
            },
            "logo": {
                "@type": "ImageObject",
                "@id": "https://funkpd.com/#logo",
                "url": "https://funkpd.com/assets/img/funkpd-hoz.svg"
            },
            "image": "https://funkpd.com/assets/img/funkpd-cover.webp",
            "contactPoint": [
                {
                    "@type": "ContactPoint",
                    "telephone": "+1-431-813-2402",
                    "email": "contact@funkpd.com",
                    "contactType": "customer support"
                }
            ],
            "sameAs": [
                "https://www.linkedin.com/company/funkproductions/",
                "https://www.crunchbase.com/organization/funk-productions",
                "https://www.bbb.org/ca/mb/winnipeg/profile/web-design/funkproductions-0057-72642",
                "https://m.yelp.com/biz/funkproductions-winnipeg",
                "https://www.instagram.com/funkpd/",
                "https://github.com/gmfunk9/",
                "https://funkpd.wordpress.com/",
                "https://www.facebook.com/funkpd"
            ],
            "hasOfferCatalog": {
                "@id": "https://funkpd.com/#catalog"
            }
        },
        {
            "@type": "WebSite",
            "@id": "https://funkpd.com/#website",
            "url": "https://funkpd.com/",
            "name": "FunkPd",
            "publisher": {
                "@id": "https://funkpd.com/#org"
            }
        },
        {
            "@type": "Person",
            "@id": "https://funkpd.com/nolan/#person",
            "name": "Nolan Phelps",
            "url": "https://funkpd.com/nolan/",
            "jobTitle": "Founder",
            "worksFor": {
                "@id": "https://funkpd.com/#org"
            },
            "sameAs": [
                "https://ca.linkedin.com/in/nolan-phelps-0a777a17b",
                "https://github.com/gmfunk9/",
                "https://www.instagram.com/funkpd/"
            ]
        },
        {
            "@type": "OfferCatalog",
            "@id": "https://funkpd.com/#catalog",
            "name": "FunkPd Packages",
            "itemListElement": [
                {
                    "@type": "OfferCatalog",
                    "name": "WordPress Rescue, Rebuilds, Stabilization, and Systems",
                    "itemListElement": [
                        {
                            "@type": "Offer",
                            "name": "Website Rescue",
                            "url": "https://funkpd.com/service/website-rescue/",
                            "itemOffered": {
                                "@type": "Service",
                                "name": "WordPress Website Rescue"
                            }
                        },
                        {
                            "@type": "Offer",
                            "name": "WordPress Rebuilds",
                            "url": "https://funkpd.com/service/rebuilds/",
                            "itemOffered": {
                                "@type": "Service",
                                "name": "WordPress Rebuilds"
                            }
                        },
                        {
                            "@type": "Offer",
                            "name": "WordPress Stabilization",
                            "url": "https://funkpd.com/stabilization/",
                            "itemOffered": {
                                "@type": "Service",
                                "name": "WordPress Stabilization"
                            }
                        },
                        {
                            "@type": "Offer",
                            "name": "Custom Systems",
                            "url": "https://funkpd.com/service/growth-systems/",
                            "itemOffered": {
                                "@type": "Service",
                                "name": "Custom WordPress Systems"
                            }
                        }
                    ]
                }
            ]
        },
        {
            "@type": "ProfessionalService",
            "@id": "https://funkpd.com/#business",
            "name": "FunkPd",
            "url": "https://funkpd.com/",
            "image": "https://funkpd.com/assets/img/funkpd-cover.webp",
            "priceRange": "$",
            "telephone": "+1-431-813-2402",
            "email": "contact@funkpd.com",
            "parentOrganization": {
                "@id": "https://funkpd.com/#org"
            },
            "address": {
                "@type": "PostalAddress",
                "streetAddress": "521 Washington Ave",
                "addressLocality": "Winnipeg",
                "addressRegion": "MB",
                "postalCode": "R2K 1M1",
                "addressCountry": "CA"
            },
            "geo": {
                "@type": "GeoCoordinates",
                "latitude": 49.9155532,
                "longitude": -97.098281
            },
            "openingHoursSpecification": [
                {
                    "@type": "OpeningHoursSpecification",
                    "dayOfWeek": [
                        "Monday",
                        "Tuesday",
                        "Wednesday",
                        "Thursday",
                        "Friday",
                        "Saturday",
                        "Sunday"
                    ],
                    "opens": "00:00",
                    "closes": "23:59"
                }
            ],
            "areaServed": [
                {
                    "@type": "City",
                    "name": "Winnipeg"
                },
                {
                    "@type": "AdministrativeArea",
                    "name": "Manitoba"
                },
                {
                    "@type": "Country",
                    "name": "Canada"
                },
                {
                    "@type": "Country",
                    "name": "Australia"
                },
                {
                    "@type": "Country",
                    "name": "Thailand"
                },
                {
                    "@type": "Country",
                    "name": "Vietnam"
                }
            ]
        }
    ]
}


{
    "@context": "https://schema.org",
    "@type": "WebPage",
    "@id": "https://funkpd.com/service/web-maintenance/#webpage",
    "url": "https://funkpd.com/service/web-maintenance/",
    "name": "WordPress Maintenance | Senior Fixes Without Retainers",
    "description": "Quarter-hour billing for real fixes: updates, breakage, speed, and security. No monthly contract, no fluff work.",
    "datePublished": "2026-04-25T09:57:18+00:00",
    "dateModified": "2026-04-25T09:57:18+00:00",
    "isPartOf": {
        "@id": "https://funkpd.com/#website"
    }
}

            
        
    
        
        
        
    
    
(function(windowObj, documentObj) {
    const gtmId = "GTM-KLWPCVT";
    const metaPixelId = "682105530429747";
    const hubspotPortalId = "22219379";
    const clarityId = "";
    let userInteracted = false;
    let pendingTrackingStart = false;
    const interactionEvents = ['click', 'keydown', 'pointerdown', 'touchstart', 'wheel'];

    function loadGtm() {
        if (!gtmId) {
            return;
        }

        if (!windowObj.dataLayer) {
            windowObj.dataLayer = [];
        }

        windowObj.dataLayer.push({
            'gtm.start': new Date().getTime(),
            event: 'gtm.js'
        });

        const existingScript = documentObj.getElementById('gtm-loader-' + gtmId);

        if (existingScript) {
            return;
        }

        const firstScript = documentObj.getElementsByTagName('script')[0];
        const gtmScript = documentObj.createElement('script');
        gtmScript.async = true;
        gtmScript.src = 'https://www.googletagmanager.com/gtm.js?id=' + gtmId;
        gtmScript.id = 'gtm-loader-' + gtmId;

        if (firstScript && firstScript.parentNode) {
            firstScript.parentNode.insertBefore(gtmScript, firstScript);
        } else if (documentObj.head) {
            documentObj.head.appendChild(gtmScript);
        }
    }

    function loadMetaPixel() {
        if (!metaPixelId) {
            return;
        }

        if (windowObj.fbq && typeof windowObj.fbq === 'function') {
            windowObj.fbq('consent', 'grant');
            windowObj.fbq('track', 'PageView');
            return;
        }

        function createFbqQueue() {
            const queue = function() {
                if (queue.callMethod) {
                    queue.callMethod.apply(queue, arguments);
                } else {
                    queue.queue.push(arguments);
                }
            };
            queue.queue = [];
            queue.loaded = true;
            queue.version = '2.0';
            queue.callMethod = queue.callMethod || null;
            queue.push = queue;
            return queue;
        }

        const fbqQueue = createFbqQueue();
        windowObj.fbq = fbqQueue;
        windowObj._fbq = fbqQueue;

        const existingPixel = documentObj.getElementById('fb-pixel-loader');

        if (existingPixel) {
            return;
        }

        const pixelScript = documentObj.createElement('script');
        pixelScript.id = 'fb-pixel-loader';
        pixelScript.async = true;
        pixelScript.src = 'https://connect.facebook.net/en_US/fbevents.js';
        const firstScript = documentObj.getElementsByTagName('script')[0];

        if (firstScript && firstScript.parentNode) {
            firstScript.parentNode.insertBefore(pixelScript, firstScript);
        } else if (documentObj.head) {
            documentObj.head.appendChild(pixelScript);
        }

        windowObj.fbq('init', metaPixelId);
        windowObj.fbq('track', 'PageView');
    }

    function loadHubspot() {
        if (!hubspotPortalId) {
            return;
        }

        const existingHubspot = documentObj.getElementById('hs-script-loader');

        if (existingHubspot) {
            return;
        }

        const hubspotScript = documentObj.createElement('script');
        hubspotScript.id = 'hs-script-loader';
        hubspotScript.async = true;
        hubspotScript.defer = true;
        hubspotScript.src = '//js.hs-scripts.com/' + hubspotPortalId + '.js';
        const firstScript = documentObj.getElementsByTagName('script')[0];

        if (firstScript && firstScript.parentNode) {
            firstScript.parentNode.insertBefore(hubspotScript, firstScript);
        } else if (documentObj.head) {
            documentObj.head.appendChild(hubspotScript);
        }
    }

    function loadClarity() {
        if (!clarityId) {
            return;
        }

        if (windowObj.clarity && typeof windowObj.clarity === 'function') {
            return;
        }

        const existingClarity = documentObj.getElementById('clarity-loader');

        if (existingClarity) {
            return;
        }

        windowObj.clarity = windowObj.clarity || function() {
            (windowObj.clarity.q = windowObj.clarity.q || []).push(arguments);
        };

        const clarityScript = documentObj.createElement('script');
        clarityScript.id = 'clarity-loader';
        clarityScript.async = true;
        clarityScript.src = 'https://www.clarity.ms/tag/' + clarityId;
        const firstScript = documentObj.getElementsByTagName('script')[0];

        if (firstScript && firstScript.parentNode) {
            firstScript.parentNode.insertBefore(clarityScript, firstScript);
        } else if (documentObj.head) {
            documentObj.head.appendChild(clarityScript);
        }
    }

    const hasTrackingTargets = Boolean(gtmId || metaPixelId || hubspotPortalId || clarityId);

    function markUserInteraction() {
        if (userInteracted) {
            return;
        }

        userInteracted = true;

        for (const eventName of interactionEvents) {
            windowObj.removeEventListener(eventName, markUserInteraction);
        }

        if (pendingTrackingStart) {
            bootTracking();
        }
    }

    function startTracking() {
        if (windowObj.funkpdTrackingLoaded) {
            return;
        }

        windowObj.funkpdTrackingLoaded = true;
        loadGtm();
        loadMetaPixel();
        loadClarity();
    }

    function bootTracking() {
        if (!hasTrackingTargets) {
            return;
        }

        if (!userInteracted) {
            pendingTrackingStart = true;
            return;
        }

        pendingTrackingStart = false;
        startTracking();
        loadHubspot();
    }

    windowObj.funkpdLoadTracking = bootTracking;

    windowObj.funkpdUnloadTracking = function() {
        const removableScriptIds = [
            'gtm-loader-' + gtmId,
            'fb-pixel-loader',
            'hs-script-loader',
            'clarity-loader'
        ];

        if (windowObj.clarity && typeof windowObj.clarity === 'function') {
            try {
                windowObj.clarity('consent', false);
                windowObj.clarity('stop');
            } catch (error) {}
        }

        for (const scriptId of removableScriptIds) {
            const node = documentObj.getElementById(scriptId);
            if (node && node.parentNode) {
                node.parentNode.removeChild(node);
            }
        }

        const gtmIframe = documentObj.querySelector('iframe[src*="googletagmanager.com/ns.html"]');
        if (gtmIframe && gtmIframe.parentNode) {
            gtmIframe.parentNode.removeChild(gtmIframe);
        }

        const fbNoscript = documentObj.querySelector('img[src*="facebook.com/tr?id="]');
        if (fbNoscript && fbNoscript.parentNode && fbNoscript.parentNode.parentNode) {
            fbNoscript.parentNode.parentNode.removeChild(fbNoscript.parentNode);
        }

        const hubspotFrame = documentObj.getElementById('hubspot-messages-iframe-container');
        if (hubspotFrame && hubspotFrame.parentNode) {
            hubspotFrame.parentNode.removeChild(hubspotFrame);
        }

        windowObj.funkpdTrackingLoaded = false;
        windowObj.dataLayer = [];
        windowObj.fbq = function() {};
        windowObj._fbq = null;
        windowObj.clarity = function() {};
        windowObj.clarity.q = [];
        pendingTrackingStart = false;
    };

    for (const eventName of interactionEvents) {
        windowObj.addEventListener(eventName, markUserInteraction, {
            once: true,
            passive: true
        });
    }
})(window, document);


(function(windowObj, documentObj) {
    const consentKey = 'funkpdAnalyticsConsent';
    const consentAllowedValue = 'allow';
    const consentDeniedValue = 'deny';
    const consentBannerId = 'analytics-consent';
    const consentButtonId = 'analytics-consent-button';
    let banner = null;
    let button = null;
    let trackingActive = true;
    let savedConsent = null;

    function setButtonState(isActive) {
        if (!button) {
            return;
        }

        button.textContent = isActive ? 'Turn off cookies' : 'Turn on cookies';
        button.setAttribute('aria-pressed', isActive ? 'true' : 'false');
    }

    function readStoredConsent() {
        try {
            return windowObj.localStorage.getItem(consentKey);
        } catch (error) {
            return null;
        }
    }

    function storeConsentAllowed() {
        try {
            windowObj.localStorage.setItem(consentKey, consentAllowedValue);
        } catch (error) {}
    }

    function storeConsentDenied() {
        try {
            windowObj.localStorage.setItem(consentKey, consentDeniedValue);
        } catch (error) {}
    }

    function activateTracking() {
        if (trackingActive) {
            storeConsentAllowed();
            if (typeof windowObj.funkpdLoadTracking === 'function') {
                windowObj.funkpdLoadTracking();
            }
            if (windowObj.clarity && typeof windowObj.clarity === 'function') {
                try {
                    windowObj.clarity('consent', true);
                } catch (error) {}
            }
            setButtonState(true);
            return;
        }

        trackingActive = true;

        if (typeof windowObj.funkpdLoadTracking === 'function') {
            windowObj.funkpdLoadTracking();
        }

        storeConsentAllowed();
        if (windowObj.clarity && typeof windowObj.clarity === 'function') {
            try {
                windowObj.clarity('consent', true);
            } catch (error) {}
        }
        setButtonState(true);
    }

    function deactivateTracking() {
        if (!trackingActive) {
            storeConsentDenied();
            setButtonState(false);
            return;
        }

        trackingActive = false;

        if (windowObj.clarity && typeof windowObj.clarity === 'function') {
            try {
                windowObj.clarity('consent', false);
            } catch (error) {}
        }

        if (typeof windowObj.funkpdUnloadTracking === 'function') {
            windowObj.funkpdUnloadTracking();
        }

        storeConsentDenied();
        setButtonState(false);
    }

    function handleButtonClick() {
        if (trackingActive) {
            deactivateTracking();
            return;
        }

        activateTracking();
    }

    function initConsentUi() {
        banner = documentObj.getElementById(consentBannerId);
        button = documentObj.getElementById(consentButtonId);

        if (!banner || !button) {
            return;
        }

        banner.removeAttribute('hidden');
        button.addEventListener('click', handleButtonClick);
        setButtonState(trackingActive);
    }

    savedConsent = readStoredConsent();

    if (savedConsent === consentDeniedValue) {
        trackingActive = false;
    } else {
        trackingActive = true;
    }

    if (trackingActive) {
        activateTracking();
    }

    if (documentObj.readyState === 'loading') {
        documentObj.addEventListener('DOMContentLoaded', initConsentUi);
    } else {
        initConsentUi();
    }
})(window, document);



    
    


    

    Skip to content

        


        
            
        
        
            root / service/web-maintenance/index.php
        
    GET_FIXED_SCOPE
    

    

    
        Menu
        
            
        
    
    
        
            
                Main
                
                    
                        
                        
                    
                    Home
                
                
                    
                        
                        
                        
                    
                    Start Here
                
                
                    
                        
                        
                        
                    
                    Rescue
                
                
                    
                        
                        
                        
                    
                    Rebuilds
                
                
                    
                        
                    
                    Stabilization
                
                
                    
                        
                        
                    
                    Work
                
                
                    
                        
                        
                    
                    Pricing
                
                
                    
                        
                    
                    Contact
                
            

            
                Resources
                
                    
                        
                        
                    
                    Service Map
                
                
                    
                        
                        
                    
                    Nolan
                
                
                    
                        
                        
                        
                    
                    Process
                
                
                    
                        
                        
                    
                    Blog
                
                
                    
                        
                    
                    FAQ
                
                
                    
                        
                        
                        
                        
                    
                    Glossary
                
            

                        
                Services
                                
                    
                        
                        
                        
                    
                    Start Here
                
                
                    
                        
                        
                        
                    
                    Website audit
                
                
                    
                        
                        
                    
                    Rebuilds
                
                
                    
                        
                    
                    Site ops
                
                
                    
                        
                        
                    
                    Technical fixes
                
                
                    
                        
                        
                    
                    Growth systems
                
                
                    
                        
                        
                        
                    
                    Website rescue
                
                
                    
                        
                        
                        
                        
                        
                    
                    Web maintenance
                
                
                    
                        
                        
                    
                    All services
                
                            
            
            
            
                    
        
            Status
            No alerts. Form updates show here.
        
    

    
    
        WordPress MaintenanceWeb Maintenance keeps stable WordPress sites moving without a default retainer. Ad hoc updates and fixes are billed in 15 minute slices.Get Fixed ScopeAd hoc defaultStable low-risk sites should pay only when they need help.Billing: 15-minute incrementsBilling in 15 minute increments with small edits batched.Batch small changesTiny edits ship together so you do not pay a minimum for every tweak.
        
            
                Support rates
                Canonical hourly support rates
            
            Stable low-risk sites should use ad hoc support instead of a default retainer.
            
                
                    $150 per hour for standard WordPress support
                    Use this for post-launch support, edits, updates, breakage, and out-of-scope work on standard WordPress stacks.
                
                
                    $175 per hour for ecommerce and complex logic
                    Use this for WooCommerce, checkout logic, integrations, custom code, and changes that need heavier testing.
                
                
                    Batch small changes
                    Tiny edits ship together so you do not pay a minimum for every tweak.
                
            
        

        
            
                When rates shift
                Discounts pause when the stack drifts from MinimalStack
            
            If the site needs cleanup or coordination, work moves to the standard rate.
            
                
                    What nulls the discount
                    Another developer changed templates or the build rules.
                
                
                    Heavy tools were added for simple content, like extra builders or ACF for plain text blocks.
                
                
                    Custom code or asset sprawl now makes edits slow or fragile.
                
                
                    Updates require coordination with another developer, designer, asset team, or SEO.
                
            
        

        
            
                Standard rates
                Clear hourly rates when Web Maintenance runs on any stack
            
            Same honest clock for every engagement; the rate matches the stack complexity.
            
                
                    Standard WordPress support
                    $150 per hour
                    For post-launch or out-of-scope work on standard WordPress stacks.
                    Billing: 15 minute increments with small edits batched.
                
                
                    Ecommerce and complex logic
                    $175 per hour
                    For WooCommerce, integrations, custom code, and changes that need heavier testing.
                    Billing: 15 minute increments with async status updates.
                
                
                    Fixed scope first
                    Scoped when possible
                    Risky changes get written scope before work starts so hourly work does not drift.
                    Billing: 15 minute increments with evidence before sign-off.
                
            
        

        
            
                Simple workflow
                Web Maintenance runs in four clear steps
            
            You see every step in writing so you know what shipped and why.
            
                
                    
                        
                            Step
                            Process
                        
                    
                    
                        
                            Step 1; Intake and access
                            We collect WordPress, hosting, and repo access plus a short list of requested changes.
                        
                        
                            Step 2; Estimate and plan
                            We map each change to a time bracket and confirm the rate that applies to your stack.
                        
                        
                            Step 3; Execute in batches
                            We ship updates in grouped batches, log time in 0.25 hour slices, and keep notes async.
                        
                        
                            Step 4; Proof and wrap
                            We share before and after notes, links to tests if used, and invoice the tracked time.
                        
                    
                
            
        

        
            
                Get fixed scope for support
                Send the change list and access; we will handle the edits with the right rate.
            
            
                Get Fixed Scope
            
        

        
            
                Frequently Asked Questions
                Common questions about Web Maintenance
            
            
                
                    What rate applies?
                    Standard WordPress support is $150 per hour. Ecommerce, integrations, checkout logic, and complex custom code are $175 per hour.
                
                
                    How do you track time?
                    I bill in 15 minute slices. If a fix takes under 10 minutes I usually do it free because it is faster to fix it than send an invoice. You save more by batching edits. One clear list costs less than a stream of small requests.
                
                
                    What access do you need?
                    I need WordPress admin access for most jobs. Hosting access is only needed for heavy work like migrations or server issues. If the site uses Git I follow your SOP but Git and WordPress together usually run at the standard rate because it adds overhead.
                
                
                    When does the standard rate apply?
                    The standard rate applies to normal WordPress support. The ecommerce rate applies when orders, integrations, custom code, or heavier testing are involved.
                
                
                    Do you work on WooCommerce?
                    Yes. I handle checkout issues, shipping, payments, product logic, templates, and plugin conflicts. WooCommerce runs at the $175 rate because every change needs testing to keep orders running.
                
                
                    How soon can you start?
                    I usually start the same day. Two days max. I work seven days a week. You only pay for real work. The clock is off when I am not fixing the site. There is no billing for logins, uploads, emails, waiting or tool downtime.
                
            
        
        
    
        Operator Identity
        Built and fixed by one person.
        You work with Nolan Phelps directly. He does the diagnosis, scope, build, fixes, and handoff himself.
        No sales layer. No project manager. No outsource chain.

        
            Since 2017
            Winnipeg
            WordPress rescue
        

        
            Start with the problem
            Meet Nolan
        
    

    
        
        Nolan Phelps
        FunkPd
    


    
        
            WordPress Risk Intake
            Get fixed scope for rescue, rebuild, or stabilization.
            Share the failure, risk, access status, and deadline. Typical response: 1 business day.
        
        
            Get Fixed Scope
            
                Call +1-431-813-2402
                Email contact@funkpd.com
            
            Operator response window: 1 business day.
        
    

    
        Since 2017 rescuing, rebuilding, and stabilizing WordPress systems.
        Delivery model: async execution with fixed-scope handoff.
        Coverage: Winnipeg HQ. Serving CA, US, and AU operators.
    

    
        
            Company
            
                About
                Nolan
                Process
                Contact
            
        

        
            Main Paths
            
                
                    Rescue
                    Contain failed builds, outages, hacks, and unsafe launches.
                
                
                    Rebuilds
                    Replace sites that are no longer worth patching.
                
                
                    Stabilize
                    Cut bloat, restore performance, and lower operating risk.
                
                
                    Extend
                    Custom systems for catalogs, commerce, and data-heavy workflows.
                
            
        

        
            Resources
            
                Work
                Pricing
                Blog
                Services
                FAQ
                Glossary
                Health Check
            
        

        
            Credibility + Contact
            
                BBB Profile
                LinkedIn
                Crunchbase
                GitHub
                contact@funkpd.com
                +1-431-813-2402
                521 Washington Ave, Winnipeg, MB R2K 1M1, Canada
            
        
    

    
        © 2026 FunkPd. Operator-Grade Web Development.
        
            Terms
            Privacy
            Sitemap
        
    

    
    
        

    
    Contact
    Site URL, problem, urgency, access, platform
  
  
      
      
      
      
      
      
      

      
            
        Name
        
      

      
        Email
        
      

      
        Phone
        
      

      
        What is the project?
        
      
      
      
      Message sent successfully.
      Send failed. Please try again.

      Send the brief
      
        We rate-limit and validate submissions. We log time, page, and an anonymized IP hash for abuse control. We use your name, email, and message to reply. We do not sell or share your details. Protected by reCAPTCHA.
        Privacy and Terms apply.
      
    

    
      
      (function(){
        function focusField(field) {
          if (!field) return;
          var input = field.querySelector('input, textarea');
          if (!input) return;
          input.focus({ preventScroll: true });
        }

        function updateLocalTestRequirements(form) {
          if (!form || form.getAttribute('data-fp-local-test') !== '1') {
            return;
          }
          var nameInput = form.querySelector('input[name="name"]');
          var emailInput = form.querySelector('input[name="email"]');
          var messageInput = form.querySelector('textarea[name="message"]');
          if (!nameInput || !emailInput || !messageInput) {
            return;
          }
          var value = (nameInput.value || '').trim().toUpperCase();
          var isTest = value === 'TESTINGFORMS' || value === 'TESTINGFORMSFAIL';
          if (isTest) {
            emailInput.removeAttribute('required');
            messageInput.removeAttribute('required');
            return;
          }
          emailInput.setAttribute('required', '');
          messageInput.setAttribute('required', '');
        }

        function updateSidebarStatus(type, message) {
          var sidebarNotice = document.querySelector('[data-sidebar-status]');
          if (!sidebarNotice) return;
          var sidebarMessage = sidebarNotice.querySelector('[data-sidebar-status-message]');
          if (!sidebarMessage) return;
          var text = message || (type === 'success' ? 'Form submitted!' : 'Send failed. Check the fields and try again.');
          sidebarMessage.textContent = text;
          sidebarMessage.classList.remove('sidebar-notice__message--success', 'sidebar-notice__message--error');
          if (type === 'success') {
            sidebarMessage.classList.add('sidebar-notice__message--success');
          }
          if (type === 'error') {
            sidebarMessage.classList.add('sidebar-notice__message--error');
          }
          sidebarNotice.hidden = false;
          sidebarNotice.classList.remove('sidebar-notice--show');
          void sidebarNotice.offsetWidth;
          sidebarNotice.classList.add('sidebar-notice--show');
        }

        function showToast(form, type, message) {
          var template = form.querySelector('.fp-toast--template.fp-toast--' + type);
          var toast = template ? template.cloneNode(true) : document.createElement('div');
          if (!template) {
            toast.className = 'fp-toast fp-toast--' + type;
            toast.setAttribute('role', type === 'success' ? 'status' : 'alert');
            toast.setAttribute('aria-live', 'polite');
          } else {
            toast.removeAttribute('hidden');
          }
          if (message) {
            toast.textContent = message;
          }
          toast.classList.add('fp-toast--show');
          if (toast.parentNode !== document.body) {
            document.body.appendChild(toast);
          }
          var hideDelay = type === 'success' ? 3000 : 4000;
          setTimeout(function(){ toast.classList.remove('fp-toast--show'); }, hideDelay);
          setTimeout(function(){
            if (toast.parentNode) {
              toast.parentNode.removeChild(toast);
            }
          }, hideDelay + 600);
          var status = form.querySelector('.contact-form__status');
          if (status) {
            status.textContent = message || (type === 'success' ? 'Message sent. We reply within one business day.' : 'Send failed. Check the fields and try again.');
            status.className = 'contact-form__status contact-form__status--' + type;
            status.hidden = false;
          }
          updateSidebarStatus(type, message);
        }

        function updateFormTiming(form) {
          var timeField = form.querySelector('input[name="form_time"]');
          if (!timeField) return;
          timeField.value = Math.floor(Date.now() / 1000).toString();
        }

        function submitWithFetch(form) {
          var action = form.getAttribute('action') || window.location.href;
          var data = new FormData(form);

          var siteKey = form.getAttribute('data-recaptcha-key');
          var tokenField = form.querySelector('input[name="g-recaptcha-response"]');

          function loadRecaptcha(callback) {
            if (!siteKey) {
              callback();
              return;
            }

            if (window.grecaptcha && typeof window.grecaptcha.ready === 'function') {
              window.grecaptcha.ready(callback);
              return;
            }

            if (window.fpRecaptchaLoading) {
              window.fpRecaptchaLoading.push(callback);
              return;
            }

            window.fpRecaptchaLoading = [callback];
            var script = document.createElement('script');
            script.src = 'https://www.google.com/recaptcha/api.js?render=' + encodeURIComponent(siteKey);
            script.async = true;
            script.defer = true;
            script.onload = function(){
              var callbacks = window.fpRecaptchaLoading || [];
              window.fpRecaptchaLoading = null;
              if (!window.grecaptcha || typeof window.grecaptcha.ready !== 'function') {
                callbacks.forEach(function(fn){ fn(); });
                return;
              }
              window.grecaptcha.ready(function(){
                callbacks.forEach(function(fn){ fn(); });
              });
            };
            document.head.appendChild(script);
          }

          function send() {
            fetch(action, {
              method: 'POST',
              body: data,
              headers: {
                'X-FP-Contact-Form': '1',
                'X-Requested-With': 'fetch',
                'Accept': 'application/json'
              }
            })
            .then(function(response){
              var contentType = response.headers.get('content-type') || '';
              if (contentType.indexOf('application/json') === -1) {
                throw new Error('bad_response');
              }
              return response.json().then(function(payload){
                return { ok: response.ok, payload: payload };
              });
            })
            .then(function(result){
              form.dataset.fpAjaxSubmitting = '0';
              if (result.payload && result.payload.sent) {
                showToast(form, 'success');
                form.reset();
                if (tokenField) {
                  tokenField.value = '';
                }
                updateFormTiming(form);
                return;
              }
              var errorMessage = result.payload && result.payload.error ? result.payload.error : '';
              showToast(form, 'error', errorMessage);
            })
            .catch(function(){
              form.dataset.fpAjaxSubmitting = '0';
              form.submit();
            });
          }

          if (siteKey) {
            loadRecaptcha(function(){
              if (!window.grecaptcha || typeof window.grecaptcha.execute !== 'function') {
                send();
                return;
              }
              window.grecaptcha.execute(siteKey, { action: 'contact' }).then(function(token){
                if (tokenField && token) {
                  tokenField.value = token;
                }
                send();
              }).catch(send);
            });
          } else {
            send();
          }
        }

        function bindForm(form) {
          if (form.dataset.fpAjaxBound === '1') {
            return;
          }
          form.dataset.fpAjaxBound = '1';
          updateLocalTestRequirements(form);
          form.addEventListener('pointerdown', function(event){
            var field = event.target.closest('.contact-form__field');
            if (!field || event.target.matches('input, textarea')) {
              return;
            }
            focusField(field);
          });
          form.addEventListener('input', function(event){
            if (!event.target || event.target.name !== 'name') {
              return;
            }
            updateLocalTestRequirements(form);
          });
          form.addEventListener('submit', function(event){
            if (form.dataset.fpAjaxSubmitting === '1') {
              return;
            }
            if (!window.fetch || !window.FormData) {
              return;
            }
            event.preventDefault();
            form.dataset.fpAjaxSubmitting = '1';
            updateLocalTestRequirements(form);
            submitWithFetch(form);
          });
        }

        var forms = document.querySelectorAll('form[data-fp-contact-form]');
        if (!forms.length) {
          return;
        }
        for (var i = 0; i < forms.length; i++) {
          bindForm(forms[i]);
        }
      })();
      

          
      (function(){
        var form = document.querySelector('[data-fp-contact-form="site_footer_contact"]');
        if (!form) return;
        var siteKey = form.getAttribute('data-recaptcha-key');
        if (!siteKey) return;
        var tokenField = form.querySelector('input[name="g-recaptcha-response"]');
        if (!tokenField) return;

        function updateToken(){
          var api = window.grecaptcha;
          if (!api) return;
          api.execute(siteKey, { action: 'contact' }).then(function(token){
            if (!token) return;
            tokenField.value = token;
          }).catch(function(){});
        }

        function loadRecaptcha(){
          if (window.grecaptcha) {
            window.grecaptcha.ready(updateToken);
            return;
          }
          if (window.fpRecaptchaLoading) {
            window.fpRecaptchaLoading.push(updateToken);
            return;
          }
          window.fpRecaptchaLoading = [updateToken];
          var script = document.createElement('script');
          script.src = 'https://www.google.com/recaptcha/api.js?render=' + encodeURIComponent(siteKey);
          script.async = true;
          script.defer = true;
          script.onload = function(){
            var callbacks = window.fpRecaptchaLoading || [];
            window.fpRecaptchaLoading = null;
            if (!window.grecaptcha) {
              return;
            }
            window.grecaptcha.ready(function(){
              callbacks.forEach(function(callback){ callback(); });
            });
          };
          document.head.appendChild(script);
        }

        function loadOnce(){
          form.removeEventListener('focusin', loadOnce);
          form.removeEventListener('pointerdown', loadOnce);
          loadRecaptcha();
        }

        form.addEventListener('submit', function(){
          if (tokenField.value !== '') {
            return;
          }
          loadRecaptcha();
          updateToken();
        });
        form.addEventListener('focusin', loadOnce);
        form.addEventListener('pointerdown', loadOnce);
      })();
      
          


  
    Direct Details
    Contact channels
  
  
    
      Email
      contact@funkpd.com
    

    
      Phone
      +1-431-813-2402
    

    
      Facebook Messenger
      m.me/funkpd
    

    
      Instagram (DM)
      @funkpd
    

    
      Threads (DM)
      @funkpd
    

    
      X / Twitter (DM)
      @funk_pd
    

    
      LinkedIn (Nolan)
      Nolan Phelps
    

    
      LinkedIn (Company)
      FunkProductions
    

    
      Office
      521 Washington Ave, Winnipeg, MB R2K 1M1, Canada
    

    
      Hours
      Support is handled by fit and urgency. Emergency routing is for real outages only.
    

    
      Response Time
      Replies within 24 hours. Priority response is reserved for active Site Ops clients and true outages.
    

    
      Socials
      Socials monitored for inquiries; support via email only.
    

    
      Privacy
      Form data is used only to reply and scope work. See our Privacy Policy.
    
  


    



{
    "@context": "https://schema.org",
    "@type": "FAQPage",
    "mainEntity": [
        {
            "@type": "Question",
            "name": "What rate applies?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "Standard WordPress support is $150 per hour. Ecommerce, integrations, checkout logic, and complex custom code are $175 per hour."
                }
        },
        {
            "@type": "Question",
            "name": "How do you track time?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "I bill in 15 minute slices. If a fix takes under 10 minutes I usually do it free because it is faster to fix it than send an invoice. You save more by batching edits. One clear list costs less than a stream of small requests."
            }
        },
        {
            "@type": "Question",
            "name": "What access do you need?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "I need WordPress admin access for most jobs. Hosting access is only needed for heavy work like migrations or server issues. If the site uses Git I follow your SOP but Git and WordPress together usually run at the standard rate because it adds overhead."
            }
        },
        {
            "@type": "Question",
            "name": "When does the standard rate apply?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "The standard rate applies to normal WordPress support. The ecommerce rate applies when orders, integrations, custom code, or heavier testing are involved."
            }
        },
        {
            "@type": "Question",
            "name": "Do you work on WooCommerce?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "Yes. I handle checkout issues, shipping, payments, product logic, templates, and plugin conflicts. WooCommerce runs at the $175 rate because every change needs testing to keep orders running."
            }
        },
        {
            "@type": "Question",
            "name": "How soon can you start?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "I usually start the same day. Two days max. I work seven days a week. You only pay for real work. The clock is off when I am not fixing the site. There is no billing for logins, uploads, emails, waiting or tool downtime."
            }
        }
    ]
}


                
        Turn off cookies