Recherche avancée

Médias (1)

Mot : - Tags -/musée

Autres articles (55)

  • Submit bugs and patches

    13 avril 2011

    Unfortunately a software is never perfect.
    If you think you have found a bug, report it using our ticket system. Please to help us to fix it by providing the following information : the browser you are using, including the exact version as precise an explanation as possible of the problem if possible, the steps taken resulting in the problem a link to the site / page in question
    If you think you have solved the bug, fill in a ticket and attach to it a corrective patch.
    You may also (...)

  • Gestion des droits de création et d’édition des objets

    8 février 2011, par

    Par défaut, beaucoup de fonctionnalités sont limitées aux administrateurs mais restent configurables indépendamment pour modifier leur statut minimal d’utilisation notamment : la rédaction de contenus sur le site modifiables dans la gestion des templates de formulaires ; l’ajout de notes aux articles ; l’ajout de légendes et d’annotations sur les images ;

  • Dépôt de média et thèmes par FTP

    31 mai 2013, par

    L’outil MédiaSPIP traite aussi les média transférés par la voie FTP. Si vous préférez déposer par cette voie, récupérez les identifiants d’accès vers votre site MédiaSPIP et utilisez votre client FTP favori.
    Vous trouverez dès le départ les dossiers suivants dans votre espace FTP : config/ : dossier de configuration du site IMG/ : dossier des média déjà traités et en ligne sur le site local/ : répertoire cache du site web themes/ : les thèmes ou les feuilles de style personnalisées tmp/ : dossier de travail (...)

Sur d’autres sites (5970)

  • My journey to Coviu

    27 octobre 2015, par silvia

    My new startup just released our MVP – this is the story of what got me here.

    I love creating new applications that let people do their work better or in a manner that wasn’t possible before.

    German building and loan socityMy first such passion was as a student intern when I built a system for a building and loan association’s monthly customer magazine. The group I worked with was managing their advertiser contacts through a set of paper cards and I wrote a dBase based system (yes, that long ago) that would manage their customer relationships. They loved it – until it got replaced by an SAP system that cost 100 times what I cost them, had really poor UX, and only gave them half the functionality. It was a corporate system with ongoing support, which made all the difference to them.

    Dr Scholz und Partner GmbHThe story repeated itself with a CRM for my Uncle’s construction company, and with a resume and quotation management system for Accenture right after Uni, both of which I left behind when I decided to go into research.

    Even as a PhD student, I never lost sight of challenges that people were facing and wanted to develop technology to overcome problems. The aim of my PhD thesis was to prepare for the oncoming onslaught of audio and video on the Internet (yes, this was 1994 !) by developing algorithms to automatically extract and locate information in such files, which would enable users to structure, index and search such content.

    Many of the use cases that we explored are now part of products or continue to be challenges : finding music that matches your preferences, identifying music or video pieces e.g. to count ads on the radio or to mark copyright infringement, or the automated creation of video summaries such as trailers.

    CSIRO

    This continued when I joined the CSIRO in Australia – I was working on segmenting speech into words or talk spurts since that would simplify captioning & subtitling, and on MPEG-7 which was a (slightly over-engineered) standard to structure metadata about audio and video.

    In 2001 I had the idea of replicating the Web for videos : i.e. creating hyperlinked and searchable video-only experiences. We called it “Annodex” for annotated and indexed video and it needed full-screen hyperlinked video in browsers – man were we ahead of our time ! It was my first step into standards, got several IETF RFCs to my name, and started my involvement with open codecs through Xiph.

    vquence logoAround the time that YouTube was founded in 2006, I founded Vquence – originally a video search company for the Web, but pivoted to a video metadata mining company. Vquence still exists and continues to sell its data to channel partners, but it lacks the user impact that has always driven my work.

    As the video element started being developed for HTML5, I had to get involved. I contributed many use cases to the W3C, became a co-editor of the HTML5 spec and focused on video captioning with WebVTT while contracting to Mozilla and later to Google. We made huge progress and today the technology exists to publish video on the Web with captions, making the Web more inclusive for everybody. I contributed code to YouTube and Google Chrome, but was keen to make a bigger impact again.

    NICTA logoThe opportunity came when a couple of former CSIRO colleagues who now worked for NICTA approached me to get me interested in addressing new use cases for video conferencing in the context of WebRTC. We worked on a kiosk-style solution to service delivery for large service organisations, particularly targeting government. The emerging WebRTC standard posed many technical challenges that we addressed by building rtc.io , by contributing to the standards, and registering bugs on the browsers.

    Fast-forward through the development of a few further custom solutions for customers in health and education and we are starting to see patterns of need emerge. The core learning that we’ve come away with is that to get things done, you have to go beyond “talking heads” in a video call. It’s not just about seeing the other person, but much more about having a shared view of the things that need to be worked on and a shared way of interacting with them. Also, we learnt that the things that are being worked on are quite varied and may include multiple input cameras, digital documents, Web pages, applications, device data, controls, forms.

    Coviu logoSo we set out to build a solution that would enable productive remote collaboration to take place. It would need to provide an excellent user experience, it would need to be simple to work with, provide for the standard use cases out of the box, yet be architected to be extensible for specialised data sharing needs that we knew some of our customers had. It would need to be usable directly on Coviu.com, but also able to integrate with specialised applications that some of our customers were already using, such as the applications that they spend most of their time in (CRMs, practice management systems, learning management systems, team chat systems). It would need to require our customers to sign up, yet their clients to join a call without sign-up.

    Collaboration is a big problem. People are continuing to get more comfortable with technology and are less and less inclined to travel distances just to get a service done. In a country as large as Australia, where 12% of the population lives in rural and remote areas, people may not even be able to travel distances, particularly to receive or provide recurring or specialised services, or to achieve work/life balance. To make the world a global village, we need to be able to work together better remotely.

    The need for collaboration is being recognised by specialised Web applications already, such as the LiveShare feature of Invision for Designers, Codassium for pair programming, or the recently announced Dropbox Paper. Few go all the way to video – WebRTC is still regarded as a complicated feature to support.

    Coviu in action

    With Coviu, we’d like to offer a collaboration feature to every Web app. We now have a Web app that provides a modern and beautifully designed collaboration interface. To enable other Web apps to integrate it, we are now developing an API. Integration may entail customisation of the data sharing part of Coviu – something Coviu has been designed for. How to replicate the data and keep it consistent when people collaborate remotely – that is where Coviu makes a difference.

    We have started our journey and have just launched free signup to the Coviu base product, which allows individuals to own their own “room” (i.e. a fixed URL) in which to collaborate with others. A huge shout out goes to everyone in the Coviu team – a pretty amazing group of people – who have turned the app from an idea to reality. You are all awesome !

    With Coviu you can share and annotate :

    • images (show your mum photos of your last holidays, or get feedback on an architecture diagram from a customer),
    • pdf files (give a presentation remotely, or walk a customer through a contract),
    • whiteboards (brainstorm with a colleague), and
    • share an application window (watch a YouTube video together, or work through your task list with your colleagues).

    All of these are regarded as “shared documents” in Coviu and thus have zooming and annotations features and are listed in a document tray for ease of navigation.

    This is just the beginning of how we want to make working together online more productive. Give it a go and let us know what you think.

    http://coviu.com/

    The post My journey to Coviu first appeared on ginger’s thoughts.

  • Organic Traffic : What It Is and How to Increase It

    19 septembre 2023, par Erin — Analytics Tips

    Organic traffic can be a website’s most valuable source of visitors. But it can also be the hardest form of traffic to acquire. While paid ads can generate traffic almost instantly, you need to invest time and energy into growing traffic from search engines.

    And it all starts with understanding exactly what organic traffic is. 

    If you want to understand what organic traffic is, how to measure it and how to generate more of it, then this article is for you.

    What is organic traffic ?

    Organic traffic is the visitors your website receives from the unpaid results on search engines like Google, Bing and DuckDuckGo. 

    The higher your website ranks in the search engine results pages and the more search terms your website ranks for, the more organic traffic your site will receive. 

    Organic traffic is highly valued by marketers, partly because it has a much higher clickthrough rate than PPC ads. Research shows the top organic result has a 39.8% CTR compared to just 2.1% for paid ads.

    So, while you can pay to appear at the top of search engines (using a platform like Google Ads, for instance), you probably won’t receive as much traffic as you would if you were to rank organically in the same search engine.

    What other types of traffic are there ? 

    Organic traffic isn’t the only type of traffic your website can get. You can also receive traffic from the following channels :

    Direct

    People familiar with your site may visit it directly, either by entering your URL into their browser or accessing it through a bookmarked link ; both scenarios are counted as direct traffic.

    Social

    Social traffic includes visits to your website from a social media platform. For example, if someone shares a link to your website on Facebook, any user who clicks on it will be counted as social traffic. 

    Websites

    Social media isn’t the only way for someone to share a link to your website. Any time a visitor finds your website by clicking on a link on another website, it will be counted as “websites”. This is also known as referral traffic on some analytics platforms. 

    Campaign

    Campaign traffic encompasses both paid and unpaid traffic sources. Paid sources include advertising on search engines and social media (also known as PPC or pay-per-click), as well as collaborations with influencers and sponsorships. Unpaid sources, such as your organisation’s email newsletters, cross-promotions with other businesses and other similar methods, are also part of this mix. 

    In simpler terms, it’s the traffic you deliberately direct to your site, and you utilise campaign tracking URLs to measure how these efforts impact your ROI.

    A word on multi-touch attribution

    If you are interested in learning more about types of traffic to track conversions, then it’s important to understand multi-touch attribution. The truth is most customers won’t just use a single traffic channel to find your website. In reality, the modern customer journey has multiple touchpoints, and customers may first find your site through an ad and then search for more about your brand on Google before going directly to your website. 

    You are at risk of under or overestimating the effectiveness of a marketing channel without using multi-touch attribution tracking. With this marketing analytics model, you can accurately weigh the impact of every channel and allocate budgets accordingly. 

    What are the benefits of organic traffic ?

    Getting more organic traffic is a common marketing goal for many companies. And it’s not surprising why. There’s a lot to love about organic traffic. 

    For starters, it’s arguably the most cost-effective traffic your site can receive. You will still need to pay to create and distribute organic content (whether it’s a blog post or product page). You don’t need to pay for it to show up in a search engine. You continue to get value from organic traffic long after you’ve created the page, too. A good piece of organic content can receive high volumes of monthly visitors for years. That’s a stark difference from paid ads, where traffic stops as soon as you turn off the ad. 

    It also puts your website in front of a massive audience, with Google alone processing over 3.5 billion searches every day. There’s a good chance that if your target audience is looking for a solution to their problems, they start with Google. 

    Organic traffic is fantastic at building brand awareness. Usually, users aren’t searching for a specific brand or company. They are searching for informational keywords (“how to brew the perfect cup of coffee”) or unbranded transactional keywords (“best home workout machine”). In both cases, customers can use search engines to become aware of your brand. 

    Finally, organic traffic brings in high-quality leads at every marketing funnel stage. Because users are searching for informational and transactional keywords, your site can receive visits from buyers at every stage of the marketing funnel, giving you multiple chances to convert them and helping to increase the number of touch points you have.

    How to check your website’s organic traffic

    You don’t need to complete complex calculations to determine your site’s organic traffic. A web analytics solution like Matomo will accurately measure your site’s organic traffic. 

    In Matomo, on the left-hand sidebar, you can access organic traffic data by clicking Acquisition and then selecting All Channels.

    You’ll find a detailed breakdown of all traffic sources, including organic traffic, within the specified timeframe. The report is set to the current day by default, but you can view organic traffic metrics over a day, week, month, year or a date range of your choice.

    If you want to take things further, you can get a detailed view of organic visitors by creating a custom report for “Visitors from Search Engines only.” By creating a custom report with the segment “Channel Type is search”, you’ll be able to combine other metrics like average actions per visit, bounce rate, goal conversions, etc., to create a comprehensive report on your organic traffic and the behavior of these visitors.

    Matomo also lets you integrate Google, Bing and Yahoo search consoles directly into your Matomo Analytics to monitor keyword performance.

    How to increase organic traffic

    Follow these six tips if you want to increase the web traffic you get organically from search engines. 

    Create more and better content

    Here’s the reality : Most websites don’t get much traffic from Google. Only 40% of sites rank on the first page, and just 23% sit in the top three results. 

    Let’s take quality first. The best content tends to rise to the top of search engines. That’s because it gets shared more, receives more backlinks and gets more user engagement. So, if you want to appear at the top of Google results, creating mediocre content probably won’t cut it. You need to go above and beyond what is already there. 

    But you can’t just create one fantastic piece of content and expect to receive thousands of visitors. You need multiple pages targeting as many search terms as possible. The more pages search engines index, the more opportunities you have to rank. Or, to put it another way, the more shots you take, the greater your chances of scoring. 

    Use keyword research tools

    While creating great content is essential, you want to ensure that content targets the right keywords. These keywords receive a suitable amount of traffic and are easy to rank for. 

    Keyword research tools like Ahrefs of Semrush are the easiest way to find high-traffic topics to write about. Specifically, you want to aim for long-tail keywords. These are search terms that contain three or more words. Think “Nike men’s basketball shoe” rather than “basketball shoe.”

    A keyword research report for "Basketball shoe"

    As you can see, long tail keywords have a lower monthly search volume (250 vs. 1,100 using the example above) than broad terms but are much easier to rank for (14 vs. 41 Keyword Difficulty).

    A keywords research report for Nike Men's basketball shoe

    While the above tools can help you find new topics to write about, Matomo’s Search Engine Keywords Performance plugin can help highlight topics you have already covered that could be expanded.

    Use Matomo's Search Engine Keywords Performance Plugin to see which keywords visitors use t find your website

    The plugin automatically connects to APIs from all significant search engines and imports all the keywords people search for when clicking on your websites into your Matomo report. 

    If you find a cluster of keywords on the same topic that generates a lot of visitors, it may be worth creating even more content on that topic. Similarly, if there’s a topic you think you have covered but isn’t generating much traffic, you can look at revising and refreshing your existing content to try to rank higher. 

    Build high-quality backlinks

    Backlinks are arguably the most important Google ranking factor and the primary way Google assesses the authoritativeness of your site and content. Backlinks strongly and positively correlate with traffic — at least according to 67.5% of respondents in a uSERP industry survey. 

    There are plenty of ways you can create high-quality backlinks that Google loves. Strategies include :

    • Creating and promoting the best content about a given topic
    • Guest posting on high-authority websites
    • Building relationships with other websites

    Ensure you avoid building low-quality spam links at all costs — such as private blog networks (PBNs), forum and comment spam links and directory links. These links won’t help your content to rank higher, and Google may even penalise your entire site if you build them. 

    Find and fix any technical Search Engine Optimisation (SEO) issues

    Search engines like Google need to be able to quickly and accurately crawl and index your website to rank your content. Unfortunately, many sites suffer from technical issues that impede search engine bots. 

    The good news is that certain tools make these issues easy to spot. Take the Matomo SEO Web Vitals feature, for instance. This lets you track a set of core web vital metrics, including :

    • Page Speed Score
    • First Contentful Paint (FCP)
    • Final Input Delay (FID)
    • Last Contentful Paint (LCP)
    • Cumulative Layout Shift (CLS)

    Take things even further by identifying major bugs and issues with your site. Crashes and other issues that impact user experience can also hurt your SEO and organic traffic efforts — so it’s best to eliminate them as soon as they occur. 

    See which bugs cause your site to crash and how you can recreate them

    Use Matomo’s Crash Analytics feature to get precise bug location information as well as the user’s interactions that triggered, the device they were using, etc. Scheduled reporting and alerts allow you to automate this task and instantly detect bugs as soon as they occur.

    Improve your on-page SEO

    As well as fixing technical issues, you should spend time optimising specific elements of your website to improve how it ranks in search engines. 

    There are several on-page elements you should optimise :

    • Image alt tags
    • URLs
    • Headings
    • Title tags
    • Internal links

    Your goal should be to include a target keyword in each element above. For example, your URL should be something like yoursite.com/keyword.

    It’s best to err on the side of caution here. Avoid adding too many keywords to each of these elements. This is called keyword stuffing, and Google may slap your site with a penalty. 

    Track your content’s performance

    One final way to increase organic traffic is to use an analytics platform to understand what content needs improving and which pages can be removed.

    Use Matomo's heatmap to see how customers interact with your wesbite

    Use an analytics platform like Matomo to see which pages generate the most organic traffic and which lag behind. This can help you prioritise your SEO efforts while highlighting pages that add no value. These pages can be completely revamped, redirected to another page or removed if appropriate. 

    Conclusion

    Organic traffic is arguably the most valuable traffic source your site can acquire. It is essential to monitor organic traffic levels and take steps to increase your organic traffic. 

    A good analytics platform can help you do both. Matomo’s powerful, open-source web analytics solution protects your data and your users’ privacy, while providing the SEO tools you need to send your organic traffic levels soaring. 

    Start a free 21-day trial now, no credit card required.

  • Matomo analytics for wordpress

    15 octobre 2019, par Matomo Core Team — Community

    Self-hosting web analytics got a whole lot easier ! Introducing Matomo for WordPress

    Be the first to try it out ! Your feedback is much needed and appreciated

    Get a fully functioning Matomo (which is comparable to Google Analytics) in seconds ! How ? With the new Matomo Analytics for WordPress plugin. 

    Web analytics in WordPress has never been easier to get, or more powerful. Matomo Analytics for WordPress is the one-stop problem solver. It’ll save you time, money and give you the insights to help your website or business succeed. 

    Best of all, we get to further the goal of decentralising the internet. Our hope is for Matomo Analytics for WordPress to spread far and wide. We’re so excited that more and more people can now get their hands on this powerful, free, open-source analytics platform, in a few clicks !

    Download now and check it out !

    What do you get ?

    • No more signing up to third party analytics service (like Google)
    • No more sending away your valuable data to a third party service (like Google)
    • Easy setup – install with a few clicks, no tracking code installation or developer knowledge needed
    • 100% accurate data – no data sampling and no data limits 
    • Full data ownership – all data is stored on your servers and no one else can see your data
    • Privacy protection / GDPR compliance
    • Ecommerce tracking out-of-the-box (Woocommerce, Easy Digital Downloads, and MemberPress) and we’re keen to add many more over time
    • Powerful features – segmenting, comparing reports, different visualisations, real-time reports, visit logs and visitor profiles, Matomo Tag Manager, dashboards, data export, APIs, and many more
    • Compared to other WordPress solutions we don’t charge you extra for basic features that should work out-of-the-box
    • Just like Matomo On-Premise, Matomo Analytics for WordPress is free

    We need your feedback !

    We all know and love the versatility of WordPress – with over 55,000 plugins and all the different ways of hosting it. However, with this great versatility comes the potential for things to be missed, so we’re keen to hear your feedback.

    Thank you ! We really appreciate your help on this ❤️

    How do you get Matomo Analytics for WordPress ?

    Log in to your WordPress and go to “Plugins => Add New”, search for “Matomo Analytics – Ethical Stats. Powerful Insights”, click on “Install” and then “Activate”.

    All you need is at least WordPress 4.8 and PHP 7.0 or later. MySQL 5.1+ is recommended. 

    The source code is available at : https://github.com/matomo-org/wp-matomo/

    In perfect harmony : Matomo and WordPress

    Matomo Analytics for WordPress

    The idea for this started two years ago when we realised the similarities between the Matomo and WordPress project. 

    Not only from a technological point of view – where both are based on PHP and MySQL and can be extended using plugins – but also from a philosophical, license and values point of view. We both believe in privacy, security, data ownership, openness, transparency, having things working out-of-the-box, simplicity etc. 

    WordPress is currently used on approximately 30% of all websites. Many of them use the self-hosted open-source WordPress version. Giving everyone in this market the opportunity to easily get a powerful web analytics platform for free, means a lot to us. We believe WordPress users get a real choice besides the standard solution of Google Analytics, and it furthers our effort and goal of decentralising the internet. 

    We’re hoping more people will be empowered to protect user privacy, have access to a great free and open-source tool, and keep control of data in their own hands.

    We hope you feel the same. Help us spread the word to your friends and get them in on this awesome new project !

    Share on facebook
    Share on twitter
    Share on linkedin

    FAQs

    Isn’t there already a WP-Matomo plugin for WordPress available ?

    Yes, the existing WP-Matomo (WP-Piwik) plugin is an awesome plugin to connect your existing Matomo On-Premise or Matomo Cloud account with WordPress. The difference is that this new plugin installs Matomo Analytics fully in your WordPress. So you get the convenience of having a powerful analytics platform within your WordPress.

    We highly recommend you install this new plugin if you use WordPress and are not running Matomo yet. 

    If you are already using Matomo on our Cloud or On-Premise, we’d still highly recommend you use WP-Matomo (WP-Piwik). So that you get an easier way of inserting the tracking code into your WordPress site and get insights faster.

    I have a high traffic website, will it be an issue ?

    If you have a lot of traffic, we’d advise you to install Matomo On-Premise separately. There’s no specific traffic threshold we can give you on when it’s better to use Matomo On-Premise. It really depends on your server. 

    We reckon if you have more than 500,000 page views a month, you may want to think about using Matomo On-Premise with WP-Matomo instead, but this is just an estimate. In general, if the load on your server is already quite high, then it might be better to install Matomo on a separate server. See also recommended server sizing for running Matomo.

    How do I report a bug or request a new feature in Matomo for WordPress ?

    Please create an issue, on our repository whenever you find a bug or if you have any suggestion or ideas of improvement. We want to build an outstanding analytics experience for WordPress !

    Have another question you’re dying to ask ? The Matomo for WordPress FAQ page might have the answer you need. 

    Matomo Analytics for WordPress newsletter

    Get ahead of the crowd – signup to our exclusive Matomo for WordPress newsletter to get the latest updates on this exciting new project.

    &lt;script type=&quot;text/javascript&quot;&gt;<br />
    (function(global) {<br />
     function serialize(form){if(!form||form.nodeName!==&quot;FORM&quot;){return }var i,j,q=[];for(i=form.elements.length-1;i&gt;=0;i=i-1){if(form.elements[i].name===&quot;&quot;){continue}switch(form.elements[i].nodeName){case&quot;INPUT&quot;:switch(form.elements[i].type){case&quot;text&quot;:case&quot;hidden&quot;:case&quot;password&quot;:case&quot;button&quot;:case&quot;reset&quot;:case&quot;submit&quot;:q.push(form.elements[i].name+&quot;=&quot;+encodeURIComponent(form.elements[i].value));break;case&quot;checkbox&quot;:case&quot;radio&quot;:if(form.elements[i].checked){q.push(form.elements[i].name+&quot;=&quot;+encodeURIComponent(form.elements[i].value))}break;case&quot;file&quot;:break}break;case&quot;TEXTAREA&quot;:q.push(form.elements[i].name+&quot;=&quot;+encodeURIComponent(form.elements[i].value));break;case&quot;SELECT&quot;:switch(form.elements[i].type){case&quot;select-one&quot;:q.push(form.elements[i].name+&quot;=&quot;+encodeURIComponent(form.elements[i].value));break;case&quot;select-multiple&quot;:for(j=form.elements[i].options.length-1;j&gt;=0;j=j-1){if(form.elements[i].options[j].selected){q.push(form.elements[i].name+&quot;=&quot;+encodeURIComponent(form.elements[i].options[j].value))}}break}break;case&quot;BUTTON&quot;:switch(form.elements[i].type){case&quot;reset&quot;:case&quot;submit&quot;:case&quot;button&quot;:q.push(form.elements[i].name+&quot;=&quot;+encodeURIComponent(form.elements[i].value));break}break}}return q.join(&quot;&amp;&quot;)};<br />
    <br />
    <br />
     function extend(destination, source) {<br />
       for (var prop in source) {<br />
         destination[prop] = source[prop];<br />
       }<br />
     }<br />
    <br />
     if (!Mimi) var Mimi = {};<br />
     if (!Mimi.Signups) Mimi.Signups = {};<br />
    <br />
     Mimi.Signups.EmbedValidation = function() {<br />
       this.initialize();<br />
    <br />
       var _this = this;<br />
       if (document.addEventListener) {<br />
         this.form.addEventListener('submit', function(e){<br />
           _this.onFormSubmit(e);<br />
         });<br />
       } else {<br />
         this.form.attachEvent('onsubmit', function(e){<br />
           _this.onFormSubmit(e);<br />
         });<br />
       }<br />
     };<br />
    <br />
     extend(Mimi.Signups.EmbedValidation.prototype, {<br />
       initialize: function() {<br />
         this.form         = document.getElementById('ema_signup_form');<br />
         this.submit       = document.getElementById('webform_submit_button');<br />
         this.callbackName = 'jsonp_callback_' + Math.round(100000 * Math.random());<br />
         this.validEmail   = /.+@.+\..+/<br />
       },<br />
    <br />
       onFormSubmit: function(e) {<br />
         e.preventDefault();<br />
    <br />
         this.validate();<br />
         if (this.isValid) {<br />
           this.submitForm();<br />
         } else {<br />
           this.revalidateOnChange();<br />
         }<br />
       },<br />
    <br />
       validate: function() {<br />
         this.isValid = true;<br />
         this.emailValidation();<br />
         this.fieldAndListValidation();<br />
         this.updateFormAfterValidation();<br />
       },<br />
    <br />
       emailValidation: function() {<br />
         var email = document.getElementById('signup_email');<br />
    <br />
         if (this.validEmail.test(email.value)) {<br />
           this.removeTextFieldError(email);<br />
         } else {<br />
           this.textFieldError(email);<br />
           this.isValid = false;<br />
         }<br />
       },<br />
    <br />
       fieldAndListValidation: function() {<br />
         var fields = this.form.querySelectorAll('.mimi_field.required');<br />
    <br />
         for (var i = 0; i &lt; fields.length; ++i) {<br />
           var field = fields[i],<br />
               type  = this.fieldType(field);<br />
           if (type === 'checkboxes' || type === 'radio_buttons' || type === 'age_check') {<br />
             this.checkboxAndRadioValidation(field);<br />
           } else {<br />
             this.textAndDropdownValidation(field, type);<br />
           }<br />
         }<br />
       },<br />
    <br />
       fieldType: function(field) {<br />
         var type = field.querySelectorAll('.field_type');<br />
    <br />
         if (type.length) {<br />
           return type[0].getAttribute('data-field-type');<br />
         } else if (field.className.indexOf('checkgroup') &gt;= 0) {<br />
           return 'checkboxes';<br />
         } else {<br />
           return 'text_field';<br />
         }<br />
       },<br />
    <br />
       checkboxAndRadioValidation: function(field) {<br />
         var inputs   = field.getElementsByTagName('input'),<br />
             selected = false;<br />
    <br />
         for (var i = 0; i &lt; inputs.length; ++i) {<br />
           var input = inputs[i];<br />
           if((input.type === 'checkbox' || input.type === 'radio') &amp;&amp; input.checked) {<br />
             selected = true;<br />
           }<br />
         }<br />
    <br />
         if (selected) {<br />
           field.className = field.className.replace(/ invalid/g, '');<br />
         } else {<br />
           if (field.className.indexOf('invalid') === -1) {<br />
             field.className += ' invalid';<br />
           }<br />
    <br />
           this.isValid = false;<br />
         }<br />
       },<br />
    <br />
       textAndDropdownValidation: function(field, type) {<br />
         var inputs = field.getElementsByTagName('input');<br />
    <br />
         for (var i = 0; i &lt; inputs.length; ++i) {<br />
           var input = inputs[i];<br />
           if (input.name.indexOf('signup') &gt;= 0) {<br />
             if (type === 'text_field') {<br />
               this.textValidation(input);<br />
             } else {<br />
               this.dropdownValidation(field, input);<br />
             }<br />
           }<br />
         }<br />
         this.htmlEmbedDropdownValidation(field);<br />
       },<br />
    <br />
       textValidation: function(input) {<br />
         if (input.id === 'signup_email') return;<br />
    <br />
         if (input.value) {<br />
           this.removeTextFieldError(input);<br />
         } else {<br />
           this.textFieldError(input);<br />
           this.isValid = false;<br />
         }<br />
       },<br />
    <br />
       dropdownValidation: function(field, input) {<br />
         if (input.value) {<br />
           field.className = field.className.replace(/ invalid/g, '');<br />
         } else {<br />
           if (field.className.indexOf('invalid') === -1) field.className += ' invalid';<br />
           this.onSelectCallback(input);<br />
           this.isValid = false;<br />
         }<br />
       },<br />
    <br />
       htmlEmbedDropdownValidation: function(field) {<br />
         var dropdowns = field.querySelectorAll('.mimi_html_dropdown');<br />
         var _this = this;<br />
    <br />
         for (var i = 0; i &lt; dropdowns.length; ++i) {<br />
           var dropdown = dropdowns[i];<br />
    <br />
           if (dropdown.value) {<br />
             field.className = field.className.replace(/ invalid/g, '');<br />
           } else {<br />
             if (field.className.indexOf('invalid') === -1) field.className += ' invalid';<br />
             this.isValid = false;<br />
             dropdown.onchange = (function(){ _this.validate(); });<br />
           }<br />
         }<br />
       },<br />
    <br />
       textFieldError: function(input) {<br />
         input.className   = 'required invalid';<br />
         input.placeholder = input.getAttribute('data-required-field');<br />
       },<br />
    <br />
       removeTextFieldError: function(input) {<br />
         input.className   = 'required';<br />
         input.placeholder = '';<br />
       },<br />
    <br />
       onSelectCallback: function(input) {<br />
         if (typeof Widget === 'undefined' || !Widget.BasicDropdown) return;<br />
    <br />
         var dropdownEl = input.parentNode,<br />
             instances  = Widget.BasicDropdown.instances,<br />
             _this = this;<br />
    <br />
         for (var i = 0; i &lt; instances.length; ++i) {<br />
           var instance = instances[i];<br />
           if (instance.wrapperEl === dropdownEl) {<br />
             instance.onSelect = function(){ _this.validate() };<br />
           }<br />
         }<br />
       },<br />
    <br />
       updateFormAfterValidation: function() {<br />
         this.form.className   = this.setFormClassName();<br />
         this.submit.value     = this.submitButtonText();<br />
         this.submit.disabled  = !this.isValid;<br />
         this.submit.className = this.isValid ? 'submit' : 'disabled';<br />
       },<br />
    <br />
       setFormClassName: function() {<br />
         var name = this.form.className;<br />
    <br />
         if (this.isValid) {<br />
           return name.replace(/\s?mimi_invalid/, '');<br />
         } else {<br />
           if (name.indexOf('mimi_invalid') === -1) {<br />
             return name += ' mimi_invalid';<br />
           } else {<br />
             return name;<br />
           }<br />
         }<br />
       },<br />
    <br />
       submitButtonText: function() {<br />
         var invalidFields = document.querySelectorAll('.invalid'),<br />
             text;<br />
    <br />
         if (this.isValid || !invalidFields) {<br />
           text = this.submit.getAttribute('data-default-text');<br />
         } else {<br />
           if (invalidFields.length || invalidFields[0].className.indexOf('checkgroup') === -1) {<br />
             text = this.submit.getAttribute('data-invalid-text');<br />
           } else {<br />
             text = this.submit.getAttribute('data-choose-list');<br />
           }<br />
         }<br />
         return text;<br />
       },<br />
    <br />
       submitForm: function() {<br />
         this.formSubmitting();<br />
    <br />
         var _this = this;<br />
         window[this.callbackName] = function(response) {<br />
           delete window[this.callbackName];<br />
           document.body.removeChild(script);<br />
           _this.onSubmitCallback(response);<br />
         };<br />
    <br />
         var script = document.createElement('script');<br />
         script.src = this.formUrl('json');<br />
         document.body.appendChild(script);<br />
       },<br />
    <br />
       formUrl: function(format) {<br />
         var action  = this.form.action;<br />
         if (format === 'json') action += '.json';<br />
         return action + '?callback=' + this.callbackName + '&amp;' + serialize(this.form);<br />
       },<br />
    <br />
       formSubmitting: function() {<br />
         this.form.className  += ' mimi_submitting';<br />
         this.submit.value     = this.submit.getAttribute('data-submitting-text');<br />
         this.submit.disabled  = true;<br />
         this.submit.className = 'disabled';<br />
       },<br />
    <br />
       onSubmitCallback: function(response) {<br />
         if (response.success) {<br />
           this.onSubmitSuccess(response.result);<br />
         } else {<br />
           top.location.href = this.formUrl('html');<br />
         }<br />
       },<br />
    <br />
       onSubmitSuccess: function(result) {<br />
         if (result.has_redirect) {<br />
           top.location.href = result.redirect;<br />
         } else if(result.single_opt_in || !result.confirmation_html) {<br />
           this.disableForm();<br />
           this.updateSubmitButtonText(this.submit.getAttribute('data-thanks'));<br />
         } else {<br />
           this.showConfirmationText(result.confirmation_html);<br />
         }<br />
       },<br />
    <br />
       showConfirmationText: function(html) {<br />
         var fields = this.form.querySelectorAll('.mimi_field');<br />
    <br />
         for (var i = 0; i &lt; fields.length; ++i) {<br />
           fields[i].style['display'] = 'none';<br />
         }<br />
    <br />
         (this.form.querySelectorAll('fieldset')[0] || this.form).innerHTML = html;<br />
       },<br />
    <br />
       disableForm: function() {<br />
         var elements = this.form.elements;<br />
         for (var i = 0; i &lt; elements.length; ++i) {<br />
           elements[i].disabled = true;<br />
         }<br />
       },<br />
    <br />
       updateSubmitButtonText: function(text) {<br />
         this.submit.value = text;<br />
       },<br />
    <br />
       revalidateOnChange: function() {<br />
         var fields = this.form.querySelectorAll(&quot;.mimi_field.required&quot;),<br />
             _this = this;<br />
    <br />
         var onTextFieldChange = function() {<br />
           if (this.getAttribute('name') === 'signup[email]') {<br />
             if (_this.validEmail.test(this.value)) _this.validate();<br />
           } else {<br />
             if (this.value.length === 1) _this.validate();<br />
           }<br />
         }<br />
    <br />
         for (var i = 0; i &lt; fields.length; ++i) {<br />
           var inputs = fields[i].getElementsByTagName('input');<br />
           for (var j = 0; j &lt; inputs.length; ++j) {<br />
             if (this.fieldType(fields[i]) === 'text_field') {<br />
               inputs[j].onkeyup = onTextFieldChange;<br />
               inputs[j].onchange = onTextFieldChange; <br />
             } else {<br />
               inputs[j].onchange = function(){ _this.validate() };<br />
             }<br />
           }<br />
         }<br />
       }<br />
     });<br />
    <br />
     if (document.addEventListener) {<br />
       document.addEventListener(&quot;DOMContentLoaded&quot;, function() {<br />
         new Mimi.Signups.EmbedValidation();<br />
       });<br />
     }<br />
     else {<br />
       window.attachEvent('onload', function() {<br />
         new Mimi.Signups.EmbedValidation();<br />
       });<br />
     }<br />
    })(this);<br />
    &lt;/script&gt;