<?xml version="1.0" encoding="utf-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom">
  <title></title>
  <subtitle></subtitle>
  <id>https://www.endpointdev.com/blog/tags/case-study/</id>
  <link href="https://www.endpointdev.com/blog/tags/case-study/"/>
  <link href="https://www.endpointdev.com/blog/tags/case-study/" rel="self"/>
  <updated>2023-12-27T00:00:00+00:00</updated>
  <author>
    <name>End Point Dev</name>
  </author>
  
    <entry>
      <title>Client Profile: J.G. Title Company</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2023/12/client-profile-j-g-title-company/"/>
      <id>https://www.endpointdev.com/blog/2023/12/client-profile-j-g-title-company/</id>
      <published>2023-12-27T00:00:00+00:00</published>
      <author>
        <name>Juan Pablo Ventoso</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2023/12/client-profile-j-g-title-company/j-g-title-company.webp&#34; alt=&#34;The J.G. Title Company logo sits in the center of an image on a blue background with futuristic designs reminiscent of circuit boards. Text on either side of the logo reads &amp;ldquo;Nationwide titling&amp;rdquo;, with text under reading &amp;ldquo;info@jgtitleco.com&amp;rdquo; and &amp;ldquo;https://jgtitleco.com&amp;rdquo;&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://jgtitleco.com/&#34;&gt;J.G. Title&lt;/a&gt; is a prominent service company specializing in automotive dealership titling and registration processes across the country. They simplify operations for their dealers, businesses, and individuals by giving tax/fee quotes, document validation, and checklists for all jurisdictions.&lt;/p&gt;
&lt;p&gt;Jordan Kivett, the owner of J.G. Title, envisioned an innovative web application to simplify dealership operations. He contacted us to request a quote for developing this solution and making his vision a reality. This project became a great opportunity for our &lt;a href=&#34;/team/&#34;&gt;.NET team&lt;/a&gt; to build a robust system with state-of-the-art technologies functioning seamlessly together.&lt;/p&gt;
&lt;h3 id=&#34;the-solution&#34;&gt;The solution&lt;/h3&gt;
&lt;p&gt;J.G. Title submitted a detailed document containing a description of the requirements for the J.G. Title Suite app along with workflow diagrams explaining their current business processes. After analyzing all the documents and having some initial meetings, we decided to divide the project into different stages, and estimate each phase of work separately. We ended up with three phases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Phase I: Create a product that allows users to enter deals into the system and retrieve the quote estimation, including taxes, fees, and charges for services across 50 states.&lt;/li&gt;
&lt;li&gt;Phase II: Implement several UI improvements such as a detailed dealership dashboard, financial management, and integration with &lt;a href=&#34;https://quickbooks.intuit.com/&#34;&gt;QuickBooks&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Phase III: Add an ambitious PDF document management section featuring document recognition, analysis, and manipulation, to perform automatic validations on the document&amp;rsquo;s contents and automatically generate PDF outputs from the deal&amp;rsquo;s details.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;tech-stack&#34;&gt;Tech stack&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://dotnet.microsoft.com/en-us/learn/dotnet/what-is-dotnet&#34;&gt;.NET&lt;/a&gt; 6 with &lt;a href=&#34;https://learn.microsoft.com/en-us/dotnet/csharp/tour-of-csharp/&#34;&gt;C#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.postgresql.org/&#34;&gt;PostgreSQL&lt;/a&gt; 14&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://rockylinux.org/&#34;&gt;Rocky Linux&lt;/a&gt; 9 with &lt;a href=&#34;https://www.nginx.com/&#34;&gt;Nginx&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We had already worked with this combination of technologies for several clients, and we are confident in the combined power in a robust database such as Postgres along with .NET 6 running in a Linux environment. It has proven to be a stable, fast, and reliable setup for our web solutions.&lt;/p&gt;
&lt;p&gt;We also used &lt;a href=&#34;https://trello.com/&#34;&gt;Trello&lt;/a&gt; for tracking the project&amp;rsquo;s progress and tasks, &lt;a href=&#34;https://github.com/&#34;&gt;GitHub&lt;/a&gt; for version control, and &lt;a href=&#34;https://visualstudio.microsoft.com/vs/&#34;&gt;Visual Studio 2022&lt;/a&gt; or &lt;a href=&#34;https://code.visualstudio.com/&#34;&gt;VS Code&lt;/a&gt; with &lt;a href=&#34;https://learn.microsoft.com/en-us/dotnet/core/tools/&#34;&gt;.NET CLI&lt;/a&gt; as a coding environment. Some of us also used &lt;a href=&#34;https://code.visualstudio.com/docs/devcontainers/tutorial&#34;&gt;VS Code dev containers&lt;/a&gt;. &lt;a href=&#34;https://www.pgadmin.org/&#34;&gt;pgAdmin&lt;/a&gt; is our usual tool to manage the local Postgres database, as well as &lt;a href=&#34;https://www.postman.com/&#34;&gt;Postman&lt;/a&gt; to test our API endpoints.&lt;/p&gt;
&lt;h3 id=&#34;the-team&#34;&gt;The team&lt;/h3&gt;
&lt;p&gt;Most of our .NET team is involved on this project. We also receive valuable help from our hosting team and our Postgres developers.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;/team/bimal-gharti-magar/&#34;&gt;Bimal Gharti Magar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/team/dan-briones/&#34;&gt;Dan Briones&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/team/dylan-wooters/&#34;&gt;Dylan Wooters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/team/juan-pablo-ventoso/&#34;&gt;Juan Pablo Ventoso&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/team/kevin-campusano/&#34;&gt;Kevin Campusano&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/team/mike-delange/&#34;&gt;Mike DeLange&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The client is also highly involved in all aspects of the development process, from requirements gathering to documenting, testing, and providing feedback. We have bi-weekly standup calls, and the entire team (End Point + J.G. Title) interacts actively through Trello, working together and updating each task as the work progresses.&lt;/p&gt;
&lt;h3 id=&#34;results&#34;&gt;Results&lt;/h3&gt;
&lt;p&gt;We began working on the project on October 25, 2022, and completed Phase I within the expected timeline, on June 7, 2023. The next phases were launched iteratively, with new deployments usually scheduled twice a week.&lt;/p&gt;
&lt;p&gt;The application is now widely used by dealerships and the J.G. Title team. They have over 200 users registered in the system, with more than 8,000 deals quoted, and new deals being added at an increasing rate.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/12/client-profile-j-g-title-company/j-g-title-suite-featured.webp&#34; alt=&#34;On the right side is an image of a laptop and phone, each running the J.G. Title Suite application. Text on the left reads &amp;ldquo;From chaos to clarity. Simplify, streamline, succeed: Embrace clarity in your dealership&amp;rsquo;s tax and title operations. Our dedicated team of specialists conducted extensive research and established partnerships with local DMVs and state Treasurers to become the trusted partner for automotive dealerships and businesses nationwide, offering efficient and reliable title and registration services. We continue transforming automotive title management on a national scale and welcome you to experience the future of automotive titling.&amp;rdquo;&#34;&gt;&lt;br&gt;
The J.G. Title Suite application, featured on the company&amp;rsquo;s website.&lt;/p&gt;
&lt;p&gt;We are continuing work on several tasks related to Phase III of the project. As the application keeps growing and users send feedback, new phases of work will surely be added to the project in the future.&lt;/p&gt;
&lt;p&gt;This partnership is a testament to our shared vision for efficiency and innovation, and we&amp;rsquo;re excited to continue reshaping the industry with J.G. Title Company!&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Data Reporting with EpiTrax</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2022/02/data-reporting-with-epitrax/"/>
      <id>https://www.endpointdev.com/blog/2022/02/data-reporting-with-epitrax/</id>
      <published>2022-02-16T00:00:00+00:00</published>
      <author>
        <name>Shannon Sandall</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2022/02/data-reporting-with-epitrax/20220107_002143-sm.webp&#34; alt=&#34;Sunset view from mountain height overlooking valley with city, lake, mountains with some snow, below yellow horizon and orange clouds under a blue sky&#34;&gt;&lt;/p&gt;
&lt;!-- Photo by Jon Jensen --&gt;
&lt;h3 id=&#34;early-covid-19-form-building-in-kansas&#34;&gt;Early COVID-19 form-building in Kansas&lt;/h3&gt;
&lt;p&gt;In March of 2020, many states struggled with disease surveillance systems that were not ready for the COVID-19 pandemic. States were forced to wait lengthy periods for their vendors or systems administrators to stand up customized forms for COVID-19 investigations.&lt;/p&gt;
&lt;p&gt;State of Kansas informatics staff were able to configure their form within a matter of hours. When the first COVID-19 records came rolling in, the state was ready to go. The Kansas Department of Health and Environment (KDHE) was using EpiTrax, a National Electronic Disease Surveillance System (NEDSS) compliant application created by the state of Utah.&lt;/p&gt;
&lt;p&gt;EpiTrax contains a powerful form-building utility that was easily customizable, allowing jurisdictional users to create forms for investigation and reporting purposes. Users could configure questions and value sets based on configurable lists, cutting down on free-text entries and ensuring data quality. Forms could be attached automatically or manually and assigned to specified agencies and conditions.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2022/02/data-reporting-with-epitrax/screenshot1.webp&#34; alt=&#34;Screenshot of form builder on Form Attributes tab with checkbox lists for Agencies and Conditions&#34;&gt;&lt;br&gt;
Screenshot of the form builder&lt;/p&gt;
&lt;h3 id=&#34;december-2021-updates&#34;&gt;December 2021 updates&lt;/h3&gt;
&lt;p&gt;Flash forward to December 2021. State of Utah developers rolled out an update to the EpiTrax form builder utility. All the previous version features, such as quick configurability and use of lists, remain, with additions to make investigators’ and informaticians’ lives easier. While the old form module was configurable, it did have room for improvement.&lt;/p&gt;
&lt;p&gt;The latest updates include question banks and value set banks that can be used across disease forms. This option allows for consistency across all forms and in reporting and analyzing data. State jurisdictions use system forms and core fields to pull data for CDC reporting purposes. The CDC NMI message mapping guides (MMGs) are the new generation of data transfer. These MMGs often require repeating fields, one option now available in the EpiTrax form builder.&lt;/p&gt;
&lt;p&gt;Users can configure forms based on the guide formats. Forms can be shared across conditions, aiding in the use of forms across comorbidities. The new form builder allows users to relate fields to existing core fields and sections. This allows the system to be more flexible and aids in creating a better flow in the user interface. The question formats accommodate many data types including address, phone and dates.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2022/02/data-reporting-with-epitrax/screenshot2.webp&#34; alt=&#34;Screenshot of select box drop-down showing widget type options&#34;&gt;&lt;br&gt;
Screenshot of the field type selector&lt;/p&gt;
&lt;h3 id=&#34;utahs-experience&#34;&gt;Utah&amp;rsquo;s experience&lt;/h3&gt;
&lt;p&gt;End Point staff discussed the new form builder with the Utah Department of Health’s (UDOH) Health Informatics Program Manager, Rachelle Boulton. Rachelle related that UDOH was able to add form fields and configure those fields in the EpiTrax NMI Module within one day when the CDC recently released version 1.1 of their COVID-19 MMG. They reached out to the CDC on December 13th to announce their readiness and were the first state to onboard on December 29th.&lt;/p&gt;
&lt;p&gt;She attributed the quick turnaround to the new form builder’s ease of use and to their use of the NMI Module. Rachelle said, “The form builder gives us the opportunity to collect data for CDC reporting requirements and allows us to make changes quickly and send data out quickly.”&lt;/p&gt;
&lt;p&gt;When asked what she likes most about the new form builder, Rachelle stated that she appreciates the new question and answer banks and their ability to quickly and efficiently create new forms that are appealing on the user interface.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2022/02/data-reporting-with-epitrax/screenshot3.webp&#34; alt=&#34;Screenshot of Manage Questions page showing value sets tab and list of values that can be used in form responses&#34;&gt;&lt;br&gt;
Screenshot of the question manager&lt;/p&gt;
&lt;h3 id=&#34;summary&#34;&gt;Summary&lt;/h3&gt;
&lt;p&gt;End Point is collaborating with our current clients to migrate data from the old form builder to the new. We are excited to help them use the new functionality.&lt;/p&gt;
&lt;p&gt;Along with this effort, we hope to build a form repository for future clients using the new form enhancements which will allow users to quickly onboard for CDC MMG reporting. These new forms would accommodate any needed state workflow changes or additions and would allow states to implement EpiTrax in a timelier manner.&lt;/p&gt;
&lt;p&gt;When asked if she had anything else to add, Rachelle said, “I really like that we try to make EpiTrax not just a surveillance system, but a change management system. We embed these changes in the workflow to make users’ lives easier.”&lt;/p&gt;
&lt;p&gt;We at End Point agree with Rachelle. We look forward to the future of EpiTrax and what we can do to help it continue to improve moving forward.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>COVID-19 Support for the Kansas Department of Health and Environment</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2020/09/covid-19-support-kansas-dept-health/"/>
      <id>https://www.endpointdev.com/blog/2020/09/covid-19-support-kansas-dept-health/</id>
      <published>2020-09-14T00:00:00+00:00</published>
      <author>
        <name>Steve Yoman</name>
      </author>
      <content type="html">
        &lt;h3 id=&#34;kansass-existing-epitrax-system&#34;&gt;Kansas’s existing EpiTrax system&lt;/h3&gt;
&lt;p&gt;End Point has worked on Kansas’s disease surveillance systems since 2011. In 2018 we migrated them from their legacy TriSano application to the open source EpiTrax surveillance system created by Utah’s Department of Health. The new EpiTrax system had been in full production for about eight months when COVID-19 cases started to grow in the United States.&lt;/p&gt;
&lt;h3 id=&#34;covid-19-help-needed&#34;&gt;COVID-19: Help needed&lt;/h3&gt;
&lt;p&gt;In March 2020, the Director of Surveillance Systems at the Kansas Department of Health and Environment (KDHE) asked us at End Point to create a web-based portal where labs, hospitals, and ad-hoc testing locations could enter COVID-19 test data. While systems existed for gathering data from labs and hospitals, they needed a way to quickly gather data from the many new and atypical sites collecting COVID-19 test information.&lt;/p&gt;
&lt;h3 id=&#34;our-approach&#34;&gt;Our approach&lt;/h3&gt;
&lt;p&gt;Since the portal was intended for people who were unfamiliar with the existing EpiTrax application, we were able to create a new design that was simple and direct, unconstrained by other applications. It required a self-registration function so users could access the system quickly and without administrative overhead, and users needed to understand how to use it without extensive training.&lt;/p&gt;
&lt;p&gt;We at End Point agreed to create the portal and dashboard for test results reporters immediately, while planning for later development of additional administrative functions. We used Ruby on Rails and Vue.js to build the portal due to their usefulness for rapid development. The Vue.js front-end JavaScript framework allowed us to quickly put together the portal UI and integrate it with the Rails back-end web services.&lt;/p&gt;
&lt;p&gt;Once approved, our team got to work setting up the environment, developing the portal application, and rigorously testing it.&lt;/p&gt;
&lt;p&gt;Here are some screenshots of the application:&lt;/p&gt;
&lt;h3 id=&#34;portal-home-page&#34;&gt;Portal home page&lt;/h3&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/09/covid-19-support-kansas-dept-health/Home-Screen.jpg&#34; alt=&#34;Kansas Reportable Disease Portal home page&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;user-registration-page&#34;&gt;User registration page&lt;/h3&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/09/covid-19-support-kansas-dept-health/newuser.png&#34; alt=&#34;Create New User Account page&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;dashboard&#34;&gt;Dashboard&lt;/h3&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/09/covid-19-support-kansas-dept-health/dashboard.jpg&#34; alt=&#34;Dashboard for searching and browsing cases&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;reporters-entry-screens&#34;&gt;Reporters’ entry screens&lt;/h3&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/09/covid-19-support-kansas-dept-health/Reporter-Data-Entry.jpg&#34; alt=&#34;Forms collecting information about reporter and patient&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/09/covid-19-support-kansas-dept-health/form-part-2.png&#34; alt=&#34;Forms collecting information about disease, speciment, and testing results&#34;&gt;&lt;/p&gt;
&lt;p&gt;The portal was launched on April 30.&lt;/p&gt;
&lt;h3 id=&#34;contact-tracers-support&#34;&gt;Contact tracers support&lt;/h3&gt;
&lt;p&gt;After the EpiTrax portal for COVID-19 was up and running, Kansas made urgent plans to hire 400 contact tracers. We updated the EpiTrax portal to accommodate this new type of user, showing contact tracers only the data they are authorized to view, while providing them the ability to make limited contact record updates and to create tasks. The project is ongoing, and eventually will be used for all diseases.&lt;/p&gt;
&lt;h3 id=&#34;epitrax-for-missouri&#34;&gt;EpiTrax for Missouri&lt;/h3&gt;
&lt;p&gt;Late this Spring, after learning of Kansas’s use of the EpiTrax platform and the powerful capabilities that it provides to the Kansas public health system, the State of Missouri reached out to us at End Point to request their own EpiTrax implementation. End Point and Missouri quickly came to agreement, and since July we have been working together build out a full production EpiTrax surveillance system for them.&lt;/p&gt;
&lt;h3 id=&#34;contact-us&#34;&gt;Contact us!&lt;/h3&gt;
&lt;p&gt;To discuss an EpiTrax project, &lt;a href=&#34;/contact/&#34;&gt;contact&lt;/a&gt; us. Our expert team is ready to help you meet your requirements.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Campendium: A Responsive, Fancy Detail Page</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2019/09/campendium-detail-page/"/>
      <id>https://www.endpointdev.com/blog/2019/09/campendium-detail-page/</id>
      <published>2019-09-09T00:00:00+00:00</published>
      <author>
        <name>Steph Skardal</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2019/09/campendium-detail-page/banner.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;This week, I was very excited to deploy a project for &lt;a href=&#34;https://www.campendium.com/&#34;&gt;Campendium&lt;/a&gt;, one of our long-time clients. As noted in &lt;a href=&#34;/blog/2019/08/campendium-updates/&#34;&gt;my recent post on Campendium updates for the year&lt;/a&gt;, Campendium has thousands of listings of places to camp and provides a great infrastructure for the development of a rich community of travelers around North America.&lt;/p&gt;
&lt;p&gt;For the past few months, I’ve been working on a significant update to Campendium’s campground detail page, the page template where in-depth information is provided for each of Campendium’s locations. This is equivalent to a product detail page on an ecommerce site.&lt;/p&gt;
&lt;p&gt;The “guts” of the update included a new detail page design with expanded responsiveness, the introduction of 360° videos, and expanded user driven content in the form of Question &amp;amp; Answer (Q&amp;amp;A or QnA), reviews, notes, nightly rates, etc. Read on to find out more and see video examples of several of the features!&lt;/p&gt;
&lt;h3 id=&#34;user-interface--responsiveness-updates&#34;&gt;User Interface &amp;amp; Responsiveness Updates&lt;/h3&gt;
&lt;p&gt;One of the things the Campendium team and I are most proud of here is the responsiveness of the new design. In the case of traveling and camping, responsiveness is important since a large amount of traffic comes from mobile devices, relative to what you might see in other industries.&lt;/p&gt;
&lt;p&gt;User images are shown as “hero images” and the user interface updates depending on the browser device and width, as shown in the following videos for &lt;a href=&#34;https://www.campendium.com/gilbert-ray-campground&#34;&gt;Gilbert Ray Campground&lt;/a&gt; and &lt;a href=&#34;https://www.campendium.com/cayuga-lake-state-park&#34;&gt;Cayuga Lake State Park&lt;/a&gt;.&lt;/p&gt;
&lt;p style=&#34;text-align:center;font-weight:bold;&#34;&gt;&lt;iframe src=&#34;https://drive.google.com/file/d/1FFF8GcztnV-KGaJ4pjDYixCbkxw6kduu/preview&#34; width=&#34;770&#34; height=&#34;450&#34;&gt;&lt;/iframe&gt;A preview of responsive behavior on the campground detail page with user submitted photos.&lt;/p&gt;
&lt;p style=&#34;text-align:center;font-weight:bold;&#34;&gt;&lt;iframe src=&#34;https://drive.google.com/file/d/1caQZT9ogh_piuTX2UDIvWGEBZse0zwnx/preview&#34; width=&#34;770&#34; height=&#34;450&#34;&gt;&lt;/iframe&gt;A second preview of responsive behavior on the campground detail page with embedded maps.&lt;/p&gt;
&lt;p&gt;Another updated design usability tweak was a sticky navigation bar to navigation throughout the page, which can get especially long with user submitted content. See how the “Overview”, “Video”, etc. links become sticky as you scroll down on the page, and the current region coming into view of the page is underlined:&lt;/p&gt;
&lt;p style=&#34;text-align:center;font-weight:bold;&#34;&gt;&lt;iframe src=&#34;https://drive.google.com/file/d/1w_MjP_HUXntYXHTG6FeREtMWwhKv4KgG/preview&#34; width=&#34;770&#34; height=&#34;450&#34;&gt;&lt;/iframe&gt;Navigation becomes fixed to the top of the browser as a user scrolls through the content.&lt;/p&gt;
&lt;p&gt;Campendium uses Ruby on Rails as a backend, a bit of &lt;a href=&#34;https://getbootstrap.com/&#34;&gt;Bootstrap&lt;/a&gt;, and &lt;a href=&#34;https://sass-lang.com/&#34;&gt;Sass&lt;/a&gt; and best practice responsive design is used throughout this updated user interface.&lt;/p&gt;
&lt;h3 id=&#34;360-videos&#34;&gt;360° Videos&lt;/h3&gt;
&lt;p&gt;The Campendium team has been hard at work creating 360 degree videos of the various locations to provide significant value to their users. These videos are now embedded into the campground detail page. Video hosting is provided by YouTube and dropped into the Campendium campground HTML template.&lt;/p&gt;
&lt;p style=&#34;text-align:center;font-weight:bold;&#34;&gt;&lt;iframe src=&#34;https://drive.google.com/file/d/12XEu-95diRRMjlqb28jD0xdj9qIWXSb7/preview&#34; width=&#34;770&#34; height=&#34;450&#34;&gt;&lt;/iframe&gt;A video in a video—a 360 degree video example.&lt;/p&gt;
&lt;p&gt;I personally think these 360° videos are awesome, especially to those visual learners out there! You can learn so much from a video that can be hard to capture in user reviews.&lt;/p&gt;
&lt;h3 id=&#34;community-qa&#34;&gt;Community Q&amp;amp;A&lt;/h3&gt;
&lt;p&gt;Another new feature with this deploy is the introduction of community driven Question &amp;amp; Answer. Users can submit questions about a campground, and users who have contributed to this campground are invited to respond (or they can opt-out site-wide to responding to questions). In addition to Q&amp;amp;A itself, user content can be “upvoted” (marked as Helpful) or flagged for an improved user content browsing experience.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2019/09/campendium-detail-page/community.png&#34; alt=&#34;Campendium community in Question &amp;amp; Answer&#34;&gt;&lt;/p&gt;
&lt;p&gt;All Q&amp;amp;A functionality is driven by JavaScript coupled with the Ruby on Rails backend.&lt;/p&gt;
&lt;h3 id=&#34;expansion-of-user-contributed-content-and-features&#34;&gt;Expansion of User Contributed Content and Features&lt;/h3&gt;
&lt;p&gt;Finally, this update includes expansion of user contributed content in addition to Q&amp;amp;A. This includes the ability for users to contribute notes, cell signal reports, and nightly rates. Reviews can now be filtered by user profile information and sorted by date or specific ranking. Reviews can also be searched by keywords and those keywords highlighted in the results. The following video demonstrates sorting and searching of reviews with highlighted keyword match:&lt;/p&gt;
&lt;p style=&#34;text-align:center;font-weight:bold;&#34;&gt;&lt;iframe src=&#34;https://drive.google.com/file/d/1G2KGfxCkOmuJm-AJE8BPXUC-OWdw1iQS/preview&#34; width=&#34;770&#34; height=&#34;450&#34;&gt;&lt;/iframe&gt;Review searchability with highlighting and filterability.&lt;/p&gt;
&lt;p&gt;All search functionality driven by JavaScript on the frontend, and a Ruby on Rails backend coupled with &lt;a href=&#34;https://github.com/sunspot/sunspot&#34;&gt;Sunspot&lt;/a&gt; and &lt;a href=&#34;https://lucene.apache.org/solr/&#34;&gt;Solr&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;who-doesnt-love-stats&#34;&gt;Who Doesn’t Love Stats?&lt;/h3&gt;
&lt;p&gt;Just for the sake of sharing stats, from GitHub, this update included:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;215 changed files&lt;/li&gt;
&lt;li&gt;6,284 additions&lt;/li&gt;
&lt;li&gt;3,924 deletions (removal / cleanup of unneeded JavaScript files)&lt;/li&gt;
&lt;/ul&gt;

      </content>
    </entry>
  
    <entry>
      <title>National Braille Press Releases Redesigned Website</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2019/08/national-braille-press-redesigned-website/"/>
      <id>https://www.endpointdev.com/blog/2019/08/national-braille-press-redesigned-website/</id>
      <published>2019-08-28T00:00:00+00:00</published>
      <author>
        <name>Elizabeth Garrett Christensen</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2019/08/national-braille-press-redesigned-website/image-0.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;End Point congratulates National Braille Press on the recent release of their &lt;a href=&#34;https://www.nbp.org/&#34;&gt;redesigned website&lt;/a&gt;, launched earlier this week! National Braille Press (NBP) supports the blind and low-vision community with events, initiatives, resources, children’s programs, and a bookstore. NBP has been working with End Point since 2002 and hosts and maintains their website, which is based on the Interchange open-source ecommerce platform.&lt;/p&gt;
&lt;h3 id=&#34;project-phases&#34;&gt;Project Phases&lt;/h3&gt;
&lt;p&gt;End Point started working with NBP on this redesign project in late 2017. We began with a user experience (UX) review &amp;amp; content strategy project which resulted in design directives for our in-house team. Design and plans were completed in mid-2018 and implementation began then. End Point built a new, more powerful search feature and developed a number of ‘cornerstone’ pages while NBP staff worked tirelessly in-house to convert the rest of the pages on their website to the new designs.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2019/08/national-braille-press-redesigned-website/image-1.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;leveraging-nbp-in-house-resources&#34;&gt;Leveraging NBP In-House Resources&lt;/h3&gt;
&lt;p&gt;NBP’s wide reach in their community and long history means their website has hundreds of content pages. This can be costly to convert, and for some non-profits, can make a redesign project cost-prohibitive. End Point engineers Greg Davidson and Marco Pessotto worked alongside NBP staff helping them learn the Bootstrap web development toolkit and the steps they needed to take to integrate each page into the new designs. Using these in-house resources dramatically reduced the overall project cost while allowing the content to be converted carefully by hand with accuracy and care.&lt;/p&gt;
&lt;h3 id=&#34;wcag-20-aa-standard&#34;&gt;WCAG 2.0, AA Standard&lt;/h3&gt;
&lt;p&gt;NBP’s user base is heavily centered in the low-vision community, so compliance with user accessibility standards was a main focus of the redesign effort. End Point worked with NBP to make sure all of the engineers on the project were trained in the Web Content Accessibility Guidelines (WCAG 2.0) AA standards and guidelines. Testing for compliance was done with &lt;a href=&#34;https://chrome.google.com/webstore/detail/axe/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US&#34;&gt;AXE&lt;/a&gt; and &lt;a href=&#34;https://wave.webaim.org/&#34;&gt;WAVE&lt;/a&gt; Chrome accessibility plugins. NBP also completed direct user testing with screen readers and devices.&lt;/p&gt;
&lt;p&gt;Congrats again to NBP on completing this project with us!&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Campendium v2019: A Summary of Recent Updates</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2019/08/campendium-updates/"/>
      <id>https://www.endpointdev.com/blog/2019/08/campendium-updates/</id>
      <published>2019-08-05T00:00:00+00:00</published>
      <author>
        <name>Steph Skardal</name>
      </author>
      <content type="html">
        &lt;p&gt;This year has brought a handful of exciting changes for &lt;a href=&#34;https://www.campendium.com/&#34;&gt;Campendium&lt;/a&gt;, one of End Point’s long-time clients, by yours truly. Created by campers for campers, Campendium has thousands of listings of places to camp, from swanky RV parks to free remote destinations, vetted by a team of full-time travelers and reviewed by over 200,000 members. I thought I would take some time to summarize these recent updates.&lt;/p&gt;
&lt;h3 id=&#34;maps-and-clustering&#34;&gt;Maps and Clustering&lt;/h3&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2019/08/campendium-updates/map-clusters.png&#34; alt=&#34;Campendium map clustering of campground locations&#34;&gt;&lt;/p&gt;
&lt;p&gt;Campendium uses &lt;a href=&#34;https://www.mapbox.com/&#34;&gt;Mapbox&lt;/a&gt; for map rendering to display campgrounds and locations throughout North America. One of the new features added this year was &lt;a href=&#34;https://docs.mapbox.com/mapbox-gl-js/example/cluster/&#34;&gt;clustering&lt;/a&gt; of campground locations, where campgrounds are grouped together and presented in a “cluster” with a size relative to how many campgrounds are in the cluster.&lt;/p&gt;
&lt;p&gt;If a user is searching for campgrounds in a broad location, they can see where campgrounds might be more densely grouped by location. Once a user zooms in zoom in a couple of clicks, the campgrounds are no longer clustered and individual campgrounds locations can be seen. While working on this update, we spent a good amount of our time tweaking and troubleshooting the optimal clustering behavior to provide the most benefit to those searching for a campground. &lt;a href=&#34;https://docs.mapbox.com/mapbox-gl-js/api/&#34;&gt;Mapbox GL JS&lt;/a&gt; works in parallel with &lt;a href=&#34;https://reactjs.org/&#34;&gt;ReactJS&lt;/a&gt;, and runs with a Ruby on Rails back-end.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2019/08/campendium-updates/map-non-clusters.jpg&#34; alt=&#34;Campendium map non-clustering of campground locations after zooming in&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;advanced-filtering&#34;&gt;Advanced Filtering&lt;/h3&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2019/08/campendium-updates/map-filtering.jpg&#34; alt=&#34;Campendium advanced filtering&#34;&gt;&lt;/p&gt;
&lt;p&gt;Another exciting was the introduction of advanced filtering in the search interface, presented in combination with map display. Users can filter campgrounds by category (e.g. Public Land, RV Parking, Parking, Dump Station), filter by price (with a slider), hookups, campground policy (e.g. age or pet restrictions), discounts, recreation, and facilities. All of this search filtering is driven by &lt;a href=&#34;https://github.com/sunspot/sunspot&#34;&gt;Sunspot&lt;/a&gt;, a Ruby on Rails gem for working with the popular &lt;a href=&#34;https://lucene.apache.org/solr/&#34;&gt;Solr&lt;/a&gt; search engine. Results can be sorted by user provided reviews, price or distance from a specific GPS location. Here, much care was given to provide the best user interface for presenting this valuable functionality.&lt;/p&gt;
&lt;h3 id=&#34;supporters-only-features&#34;&gt;“Supporters Only” Features&lt;/h3&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2019/08/campendium-updates/supporters.jpg&#34; alt=&#34;Campendium Supporters only, Subscriptions&#34;&gt;&lt;/p&gt;
&lt;p&gt;Another recent update to Campendium includes functionality to offer user subscriptions. Registered users can sign up to support Campendium on a monthly or annual basis, and subscriptions are set to auto-renew at the end of their subscription period. This paid support hides advertisements throughout the site (advertisements are controlled by a third party), and advanced filtering on cell reception. There are plans to expand supporter features in the future. Ruby on Rails combined with &lt;a href=&#34;https://stripe.com/docs/stripe-js/reference&#34;&gt;StripeJS&lt;/a&gt; is used to manage subscription payments, and Ruby on Rails also serves as a backend for &lt;a href=&#34;https://developer.apple.com/in-app-purchase/&#34;&gt;In-App Purchases&lt;/a&gt; of subscriptions from the App store.&lt;/p&gt;
&lt;h3 id=&#34;always-responsive-and-latency-aware&#34;&gt;Always Responsive and Latency-Aware&lt;/h3&gt;
&lt;p&gt;Because a large portion of the Campendium visitors are on the road, it’s important to have both a responsive design and to build for bandwidth limitations for users. Throughout the development of these new features, responsive and mobile friendly designs were implemented leveraging &lt;a href=&#34;https://sass-lang.com/&#34;&gt;Sass&lt;/a&gt;, sometimes requiring help from the rest of the knowledgeable &lt;a href=&#34;/team/&#34;&gt;End Point team&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Many of the pages throughout the site are fully cached including the homepage, search result pages, and campground detail page, and cookies are used to indicate user status. In some cases, user submitted campground images are lazy-loaded to mitigate bandwidth limitations.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2019/08/campendium-updates/mobile.jpg&#34; alt=&#34;Mobile, responsive design for Campendium&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;whats-next&#34;&gt;What’s Next?&lt;/h3&gt;
&lt;p&gt;While I didn’t go into much technical depth on these updates, I am happy that the updates represent a broad spectrum of full-stack development skills featuring nginx, Ruby on Rails, 3rd party integration including StripeJS, MapboxGL and IAP (Apple), a JavaScript framework with ReactJS, and working with Ruby gems to leverage other tools, for example, Solr (Sunspot) and Sass.&lt;/p&gt;
&lt;p&gt;In the future, Campendium plans to continue using these tools to see a more interactive, social campground detail page, and has plans to expand outside of North America. You can visit Campendium &lt;a href=&#34;https://www.campendium.com/&#34;&gt;here&lt;/a&gt;, or find them on Instagram &lt;a href=&#34;https://www.instagram.com/campendium/?hl=en&#34;&gt;here&lt;/a&gt; to follow their exciting announcements!&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Client Case Study: Vervante—​Publishing, Production and Fulfillment Services</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2017/08/client-case-study-vervante-publishing/"/>
      <id>https://www.endpointdev.com/blog/2017/08/client-case-study-vervante-publishing/</id>
      <published>2017-08-28T00:00:00+00:00</published>
      <author>
        <name>Greg Hanson</name>
      </author>
      <content type="html">
        &lt;h3 id=&#34;a-real-life-scenario&#34;&gt;A real-life scenario&lt;/h3&gt;
&lt;p&gt;The following is a real-life example of services we have provided for one of our clients.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://store.vervante.com/c/affil/index.html&#34;&gt;Vervante Corporation&lt;/a&gt; provides a print on demand and order fulfillment service for thousands of customers, in their case, “Authors”. Vervante needed a way for these authors to keep track of their products. Essentially they needed an &lt;a href=&#34;https://en.wikipedia.org/wiki/Inventory_management_software&#34;&gt;Inventory management system&lt;/a&gt;. So we designed a complete system from the ground up that allows Vervante’s authors many custom functions that simply are not offered in a pre-built package anywhere.&lt;/p&gt;
&lt;p&gt;This is also a good time to mention that &lt;strong&gt;you should always view your web presence, in fact your business itself, as a process&lt;/strong&gt;, not a one time “setup”. Your products will change, your customers will change, the web will change, &lt;strong&gt;everything&lt;/strong&gt; will change. &lt;strong&gt;If you want your business to be successful, you will change.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&#34;some-specifics&#34;&gt;Some Specifics&lt;/h3&gt;
&lt;p&gt;While it is beyond the scope of this case study to describe all of the programs that were developed for Vervante, it will be valuable for the reader to sample just a few of the areas to understand how diverse a single business can be. Here are a few of the functions we have built from scratch, over several years to continue to provide Vervante, their authors, and even their vendors with efficient processes to achieve their daily business needs.&lt;/p&gt;
&lt;h3 id=&#34;requirements&#34;&gt;Requirements&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Author Requirement—​First, in some cases, the best approach to a problem is to use someone else’s solution! Vervante’s authors have large data files that are converted to a product, and then shipped on demand as the orders come in. So we initially provided a custom file transfer process so that customers could directly upload their files to a server we set up for Vervante. Soon Vervante’s rapid growth outpaced the efficacy of this system, so we investigated and determined the most efficient and cost-effective approach was to incorporate a 3rd party service. So we recommended a well known file transfer service and wrote a program to communicate with the file transfer service API. Now a client can easily describe and upload large files to Vervante.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;object class=&#34;BLOG_video_class&#34; classid=&#34;clsid:D27CDB6E-AE6D-11cf-96B8-444553540000&#34; codebase=&#34;http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0&#34; height=&#34;266&#34; id=&#34;BLOG_video-f735687e5d91b6e5&#34; width=&#34;320&#34;&gt;&lt;param name=&#34;movie&#34; value=&#34;https://www.youtube.com/get_player&#34;/&gt;
&lt;param name=&#34;bgcolor&#34; value=&#34;#FFFFFF&#34;/&gt;
&lt;param name=&#34;allowfullscreen&#34; value=&#34;true&#34;/&gt;
&lt;param name=&#34;flashvars&#34; value=&#34;flvurl=https://redirector.googlevideo.com/videoplayback?requiressl%3Dyes%26id%3Df735687e5d91b6e5%26itag%3D5%26source%3Dblogger%26app%3Dblogger%26cmo%3Dsecure_transport%253Dyes%26cmo%3Dsensitive_content%253Dyes%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1508990116%26sparams%3Drequiressl,id,itag,source,ip,ipbits,expire%26signature%3D99FD6C851283A8BC063EB63455AA30622B1A8437.3D4F2FF3F744A46AD71889580CB2708476EA61F4%26key%3Dck2&amp;iurl=https://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3Df735687e5d91b6e5%26offsetms%3D5000%26itag%3Dw160%26sigh%3DIi_vgaZOeZV9xdyNjeqlp9MvQPM&amp;autoplay=0&amp;ps=blogger&#34;/&gt;
&lt;embed allowfullscreen=&#34;true&#34; bgcolor=&#34;#FFFFFF&#34; flashvars=&#34;flvurl=https://redirector.googlevideo.com/videoplayback?requiressl%3Dyes%26id%3Df735687e5d91b6e5%26itag%3D5%26source%3Dblogger%26app%3Dblogger%26cmo%3Dsecure_transport%253Dyes%26cmo%3Dsensitive_content%253Dyes%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1508990116%26sparams%3Drequiressl,id,itag,source,ip,ipbits,expire%26signature%3D99FD6C851283A8BC063EB63455AA30622B1A8437.3D4F2FF3F744A46AD71889580CB2708476EA61F4%26key%3Dck2&amp;iurl=https://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3Df735687e5d91b6e5%26offsetms%3D5000%26itag%3Dw160%26sigh%3DIi_vgaZOeZV9xdyNjeqlp9MvQPM&amp;autoplay=0&amp;ps=blogger&#34; height=&#34;266&#34; src=&#34;https://www.youtube.com/get_player&#34; type=&#34;application/x-shockwave-flash&#34; width=&#34;320&#34;/&gt;&lt;/object&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&#34;https://drive.google.com/file/d/0B_fTO4RaXomtd3REUWR3U1hERmM/view&#34;&gt;View File Save Process&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Storage Requirement—​The remote storage of these large files caused Vervante a dramatic inefficiency as relates to access times, as they worked daily on these files to format, organize, and create product masters. So we needed to provide Vervante with a local server to act as a file server that was on their local network (LAN), where it could be rapidly accessed and manipulated. This was a challenge, as Vervante did not have IT personnel on site. So we purchased an appropriate server, set up everything in our offices, and shipped the complete server to them! They plugged the server into their local network, and with a long phone call, we had the server up and running and remotely managed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Author Requirement—​On the website, the authors first wanted to see what they had in inventory. Some customers provided Vervante with some product components that needed to be included with a complete product, while others relied on Vervante to build all components of their products. They also requested a way to set minimum inventory stock requirements.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So we built an interface that would allow authors to:&lt;/p&gt;
&lt;p&gt;(a) See their current stock levels for all products,&lt;/p&gt;
&lt;p&gt;(b) View outstanding orders for these items,&lt;/p&gt;
&lt;p&gt;(c) Set minimum inventory levels that they would like to have maintained at the fulfillment warehouse.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;margin-top:20px;&#34;&gt;&lt;a href=&#34;/blog/2017/08/client-case-study-vervante-publishing/image-0-big.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;&lt;img border=&#34;0&#34; data-original-height=&#34;441&#34; data-original-width=&#34;1211&#34; height=&#34;233&#34; src=&#34;/blog/2017/08/client-case-study-vervante-publishing/image-0.png&#34; width=&#34;640&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;For example a finished product may consist of a book, a CD, and a DVD. A customer may supply the CD and require Vervante to produce the book and the DVD “on demand” for the product. We created a system that tracked all items at a “base” item level, and then allowed Vervante to “build” products with as many of these “base” items as necessary, to create the final product. The base items could be combined to create an item, and two or more items could be combined to produce yet another item. It is a recursive item inventory system, built from scratch specifically for Vervante.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2017/08/client-case-study-vervante-publishing/image-1.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;&lt;img border=&#34;0&#34; data-original-height=&#34;437&#34; data-original-width=&#34;1227&#34; src=&#34;/blog/2017/08/client-case-study-vervante-publishing/image-1.png&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Vervante Vendor (fulfillment warehouse) Requirement—​Additionally, the &lt;em&gt;fulfillment warehouse&lt;/em&gt; that receives, stores, builds and ships end user products, needed access to this system. They had several needs including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Retrieving pending orders for shipment&lt;/li&gt;
&lt;li&gt;Creating packing / pick slips for the orders&lt;/li&gt;
&lt;li&gt;Create shipping labels for orders&lt;/li&gt;
&lt;li&gt;Manage returns&lt;/li&gt;
&lt;li&gt;Input customer supplied inventory&lt;/li&gt;
&lt;li&gt;Input fulfillment created inventory&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In our administrative user interface for the fulfillment house, we developed a series of customer specific processes to address the above needs. Here is a high level example of how a few of the items on the list above are achieved:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;- The fulfillment house logs into the user admin first thing in the morning, and prints the outstanding orders.
- The “orders” are formatted similar to a packing slip, and each slip has all line items of the order, and a bar code imprinted on the slip.
- This document is used as a “pick” slip, and is placed in a “pick” basket. The user then goes through the warehouse, gathers the appropriate items, and when complete the order is placed on a feed belt to the shipper location.
- When the basket lands in front of the shipper, that person checks the contents of the basket against the slip, and then uses a bar code scanner to scan the order. That scan triggers a query into our system that returns all applicable shipping data into an Endicia or UPS system. 
- A shipping label is created, and the shipping cost and tracking information is returned to the our system.
- Additionally the inventory is decremented accordingly when the order receives a shipping label and tracking number.
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Requirements: administrative / accounting—​Vervante also needed an administrative / accounting arm, designed to control all of the accounting functions such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Recording customers’ fulfillment charges&lt;/li&gt;
&lt;li&gt;Recording customers’ sales (Vervante sells product for the customers as well as fulfilling outside orders)&lt;/li&gt;
&lt;li&gt;Determining fulfillment vendor fees and payments&lt;/li&gt;
&lt;li&gt;Tracking shipping costs&lt;/li&gt;
&lt;li&gt;Monthly billing of all customers&lt;/li&gt;
&lt;li&gt;Monthly payments for all customers.&lt;/li&gt;
&lt;li&gt;Interface with in-house accounting systems and keeping systems in sync&lt;/li&gt;
&lt;li&gt;Tracking and posting outside order transactions&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The above described processes are just a few of the processes that we developed from scratch, and matched to Vervante’s needs. It is also a tiny portion of their system.&lt;/p&gt;
&lt;h3 id=&#34;last-but-not-least&#34;&gt;Last, but not least&lt;/h3&gt;
&lt;p&gt;Oh, and one other interesting fact: When Vervante first came to us several years ago, they had fewer than 20 customers. Today, they provide order fulfillment and print on demand services for nearly 4000 customers. So when we say to plan ahead for growth, we have experience in that area.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>co:collective Doable Innovation Software</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2017/07/cocollective-doable-innovation-software/"/>
      <id>https://www.endpointdev.com/blog/2017/07/cocollective-doable-innovation-software/</id>
      <published>2017-07-26T00:00:00+00:00</published>
      <author>
        <name>Elizabeth Garrett Christensen</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;a href=&#34;http://www.cocollective.com/&#34;&gt;co:collective&lt;/a&gt; is a growth accelerator that works with leadership teams to conceive and execute innovation in the customer experience using a proprietary methodology called StoryDoing.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.doable.com/&#34;&gt;Doable&lt;/a&gt;, one of co:collective’s recent innovations, is a cloud-based platform designed to empower employees to meaningfully contribute and collaborate on ideas that move their business forward. The tool allows companies to solicit ideas from employees at all levels of an organization, filter down those ideas, make decisions as a team, and then implement a project—​all the while collaborating in a fun and easy-to-use application. Over 200 companies across multiple sectors use Doable to create new products, new features, and problem solve to keep their business growing.&lt;/p&gt;
&lt;p&gt;co:collective engaged End Point’s front-end developer &lt;a href=&#34;/blog/authors/kamil-ciemniewski/&#34;&gt;Kamil Ciemniewski&lt;/a&gt; to work with their in-house development team led by Tommy Dunn. Kamil joined the Doable effort to refactor the Doable application which was moving from a classic Ruby on Rails-based application to an Angular frontend application with a Ruby on Rails backend. Kamil has been working with Doable since March to complete the application re-write and the project has gone immensely well. Kamil brings extensive frontend and backend knowledge to co:collective and together they’ve been able to refactor their site to be more efficient and powerful than before.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2017/07/cocollective-doable-innovation-software/image-0-big.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;&lt;img border=&#34;0&#34; data-original-height=&#34;890&#34; data-original-width=&#34;1600&#34; height=&#34;223&#34; src=&#34;/blog/2017/07/cocollective-doable-innovation-software/image-0.png&#34; width=&#34;400&#34;/&gt;&lt;/a&gt;&lt;/div&gt;

      </content>
    </entry>
  
    <entry>
      <title>TriSano Case Study</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2017/01/trisano-case-study/"/>
      <id>https://www.endpointdev.com/blog/2017/01/trisano-case-study/</id>
      <published>2017-01-24T00:00:00+00:00</published>
      <author>
        <name>Elizabeth Garrett Christensen</name>
      </author>
      <content type="html">
        &lt;h3 id=&#34;overview&#34;&gt;Overview&lt;/h3&gt;
&lt;p&gt;End Point has been working with state and local health agencies since 2008. We host disease outbreak surveillance and management systems and have expertise providing clients with the sophisticated case management tools they need to deliver in-house analysis, visualization, and reporting—​combined with the flexibility to comply with changing state and federal requirements. End Point provides the hosting infrastructure, database, reporting systems, and customizations that agencies need in order to service to their populations.&lt;/p&gt;
&lt;p&gt;Our work with health agencies is a great example of End Point’s ability to use our experience in open source technology, Ruby on Rails, manage and back up large secure datasets, and integrate reporting systems to build and support a full-stack application. We will discuss one such client in this case study.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; float: right; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2017/01/trisano-case-study/image-0.jpeg&#34; imageanchor=&#34;1&#34;&gt;&lt;img border=&#34;0&#34; height=&#34;376&#34; src=&#34;/blog/2017/01/trisano-case-study/image-0.jpeg&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3 id=&#34;why-end-point&#34;&gt;Why End Point?&lt;/h3&gt;
&lt;p&gt;End Point is a good fit for this project because of our expertise in several areas including reporting and our hosting capabilities. End Point has had a long history of consultant experts in PostgreSQL and Ruby on Rails, which are the core software behind this application.&lt;/p&gt;
&lt;p&gt;Also, End Point specializes in customizing open-source software, which can save not-for-profit and state agencies valuable budget dollars they can invest in other social programs.&lt;/p&gt;
&lt;p&gt;Due to the secure nature of the medical data in these database, we and our clients must adhere to all HIPAA and CDC policies regarding hosting of data handling, server hosting, and staff authorization and access auditing.&lt;/p&gt;
&lt;h3 id=&#34;team&#34;&gt;Team&lt;/h3&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; float: left; text-align: center; padding:10px;&#34;&gt;&lt;a href=&#34;/blog/2017/01/trisano-case-study/image-1-big.jpeg&#34; imageanchor=&#34;1&#34;&gt;&lt;img border=&#34;0&#34; height=&#34;100&#34; src=&#34;/blog/2017/01/trisano-case-study/image-1.jpeg&#34; width=&#34;100&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h4 id=&#34;steve-yoman&#34;&gt;Steve Yoman&lt;/h4&gt;
&lt;p&gt;Steve serves as the project manager for both communication and internal development for End Point’s relationship with the client. Steve brings many years in project management to the table for this job and does a great job keeping track of every last detail, quote, and contract item.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; float: left; text-align: center; padding:10px;&#34;&gt;&lt;a href=&#34;/blog/2017/01/trisano-case-study/image-2-big.jpeg&#34; imageanchor=&#34;1&#34;&gt;&lt;img border=&#34;0&#34; height=&#34;100&#34; src=&#34;/blog/2017/01/trisano-case-study/image-2.jpeg&#34; width=&#34;100&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h4 id=&#34;selvakumar-arumugam&#34;&gt;Selvakumar Arumugam&lt;/h4&gt;
&lt;p&gt;Selva is one of those rare engineers who is gifted with both development and DevOps expertise. He is the main developer on daily tasks related to the disease tracking system. He also does a great job navigating a complex hosting environment and has helped the client make strides towards their future goals.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; float: left; text-align: center; padding:10px;&#34;&gt;&lt;a href=&#34;/blog/2017/01/trisano-case-study/image-3-big.jpeg&#34; imageanchor=&#34;1&#34;&gt;&lt;img border=&#34;0&#34; height=&#34;100&#34; src=&#34;/blog/2017/01/trisano-case-study/image-3.jpeg&#34; width=&#34;100&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h4 id=&#34;josh-tolley&#34;&gt;Josh Tolley&lt;/h4&gt;
&lt;p&gt;Josh is one of End Point’s most knowledgeable database and reporting experts. Josh’s knowledge of PostgreSQL is extremely helpful to make sure that the data is secure and stable. He built and maintains a standalone reporting application based on Pentaho.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; float: right; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2017/01/trisano-case-study/image-4-big.jpeg&#34; imageanchor=&#34;1&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2017/01/trisano-case-study/image-4.jpeg&#34; width=&#34;500&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3 id=&#34;application&#34;&gt;Application&lt;/h3&gt;
&lt;p&gt;The disease tracking system consists of several applications including a web application, reporting application, two messaging areas, and SOAP services that relay data between internal and external systems.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TriSano&lt;/strong&gt;: The disease tracking web app is an open source Ruby on Rails application based on the TriSano product, originally built at the Collaborative Software Initiative. This is a role-based web application where large amounts of epidemiological data can be entered manually or by data transfer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pentaho&lt;/strong&gt;: Pentaho is a PostgreSQL reporting application that allows you to run a separate reporting service or embed reports into your website. Pentaho has a community version and an enterprise version, which is what is used on this particular project. This reporting application provides OLAP services, dashboarding, and generates ad hoc and static reports. Josh Tolley customized Pentaho so that the client can download or create custom reports depending on their needs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Two Messaging Area applications&lt;/strong&gt;: The TriSano system also serves as the central repository for messaging feeds used to collect data from local health care providers, laboratories throughout the state, and the CDC.&lt;/p&gt;
&lt;p&gt;SOAP services run between the TriSano web app, the Pentaho reporting application, and the client’s data systems translate messages into the correct formats and relay the information to each application.&lt;/p&gt;
&lt;h3 id=&#34;into-the-future&#34;&gt;Into the Future&lt;/h3&gt;
&lt;p&gt;Based on the success over 9+ years working on this project, the client continues to work with their End Point team to manage their few non open-source software licenses, create long term security strategies, and plan and implement all of their needs related to the continuous improvement and changes in epidemiology tracking. We partner with the client so they can focus their efforts on reading results and planning for the future health of their citizens. This ongoing partnership is something End Point is very proud to be a part of and we hope to continue our work in this field well into the future.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Client Case Study: Carjojo</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2016/12/client-case-study-carjojo/"/>
      <id>https://www.endpointdev.com/blog/2016/12/client-case-study-carjojo/</id>
      <published>2016-12-23T00:00:00+00:00</published>
      <author>
        <name>Elizabeth Garrett Christensen</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;a href=&#34;https://web.archive.org/web/20161221010712/https://www.carjojo.com/&#34;&gt;Carjojo&lt;/a&gt;’s site makes use of some of the best tools on the market today for accessing and displaying data. Carjojo is a car buying application that takes data about car pricing, dealer incentives, and rebate programs and aggregates that into a location-specific vehicle pricing search tool. The Carjojo work presented a great opportunity for End Point to utilize our technical skills to build a state-of-the-art application everyone is very proud of. End Point worked on the Carjojo development project from October of 2014 through early 2016, and the final Carjojo application launched in the summer of 2016. This case study shows that End Point can be a technology partner for a startup, enabling the client to maintain their own business once our part of the project is over.&lt;/p&gt;
&lt;h3 id=&#34;why-end-point&#34;&gt;Why End Point?&lt;/h3&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; float: right; text-align: center;&#34;&gt;&lt;img height=&#34;375&#34; id=&#34;docs-internal-guid-bf89d7d8-193d-dd5c-ed85-19fbe48e18e4&#34; src=&#34;/blog/2016/12/client-case-study-carjojo/image-0.png&#34; style=&#34;border: medium none; transform: rotate(0rad);&#34; width=&#34;338&#34;/&gt;&lt;/div&gt;
&lt;h4 id=&#34;reputation-in-full-stack-development&#34;&gt;Reputation in full stack development&lt;/h4&gt;
&lt;p&gt;End Point has deep experience with full stack development so for a startup getting advice from our team can prove really helpful when deciding what technologies to implement and what timelines are realistic. Even though the bulk of the Carjojo work focused on specific development pieces, having developers available to help advise on the entire stack allows a small startup to leverage a much broader set of skills.&lt;/p&gt;
&lt;h4 id=&#34;startup-budget-and-timelines&#34;&gt;Startup Budget and Timelines&lt;/h4&gt;
&lt;p&gt;End Point has worked with a number of startups throughout our time in the business. Startups require particular focused attention on budget and timelines to ensure that the minimum viable product can be ready on time and that the project stays on budget. Our consultants focus on communication with the client and advise them on how to steer the development to meet their needs, even if those shift as the project unfolds.&lt;/p&gt;
&lt;h4 id=&#34;client-side-development-team&#34;&gt;Client Side Development Team&lt;/h4&gt;
&lt;p&gt;One of the best things about a lot of our clients is their technological knowledge and the team they bring to the table. In the case of Carjojo, End Point developers fit inside of their Carjojo team to build parts that they were unfamiliar with. End Point developers are easy to work with and already work in a remote development environment, so working in a remote team is a natural fit.&lt;/p&gt;
&lt;h4 id=&#34;client-side-project-management&#34;&gt;Client Side Project Management&lt;/h4&gt;
&lt;p&gt;End Point works on projects where either the project management is done in-house or by the client. In the case of a project like Carjojo where the client has technical project management resources, our engineers work within that team. This allows a startup like Carjojo insight into the project on a daily basis.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; float: left; text-align: center;&#34;&gt;&lt;img height=&#34;350&#34; id=&#34;docs-internal-guid-adf4efb0-193f-f2b6-279f-301698d2fdc2&#34; src=&#34;/blog/2016/12/client-case-study-carjojo/image-1.png&#34; style=&#34;-webkit-transform: rotate(0.00rad); border: none; transform: rotate(0.00rad);&#34; width=&#34;150&#34;/&gt;&lt;/div&gt;
&lt;h3 id=&#34;project-overview&#34;&gt;Project Overview&lt;/h3&gt;
&lt;p&gt;The main goal of the Carjojo project was to aggregate several data sources on car price and use data analytics to provide useful shopper information, and display that for their clients.&lt;/p&gt;
&lt;p&gt;Carjojo’s staff had experience in the car industry and leveraged that to build a sizeable database of information. Analytics work on the database provided another layer of information, creating a time- and location-specific market value for a vehicle.&lt;/p&gt;
&lt;p&gt;Carjojo kept the bulk of the database collection and admin work in house, as well as provided an in-house designer that closely worked with them on their vision for the project. End Point partnered to do the API architecture work as well as the front end development.&lt;/p&gt;
&lt;p&gt;A major component of this project was using a custom API to pull information from the database and display it quickly with high end, helpful infographics. Carjojo opted to use APIs so that the coding work would seamlessly integrate with future plans for a mobile application, which normally require a substantial amount of recoding.&lt;/p&gt;
&lt;p&gt;Creating a custom API also allows Carjojo to work with future partners and leverage their data and analytics in new ways as their business grows.&lt;/p&gt;
&lt;h3 id=&#34;team&#34;&gt;Team&lt;/h3&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; float: left; text-align: center;&#34;&gt;&lt;img height=&#34;151&#34; id=&#34;docs-internal-guid-c5221843-1937-962a-43e0-fc2b316dbed6&#34; src=&#34;/blog/2016/12/client-case-study-carjojo/image-2.png&#34; style=&#34;border: medium none; transform: rotate(0rad);&#34; width=&#34;151&#34;/&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Patrick Lewis&lt;/strong&gt;: End Point project manager and front end developer. Patrick led development of the AngularJS front end application which serves as the main customer car shopping experience on the Carjojo site. He also created data stories using combinations of integrated Google Maps, D3/DimpleJS charts, and data tables to aid buyers with car searches and comparisons.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; float: left; text-align: center;&#34;&gt;&lt;img height=&#34;153&#34; id=&#34;docs-internal-guid-adf4efb0-1938-fb69-fe18-cada954bb90b&#34; src=&#34;/blog/2016/12/client-case-study-carjojo/image-3.png&#34; style=&#34;border: medium none; transform: rotate(0rad);&#34; width=&#34;153&#34;/&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Matt Galvin:&lt;/strong&gt; Front end developer. Matt led the efforts for data-visualization with D3 and DimpleJS. He created Angular services that were used to communicate with the backend, used D3 and DimpleJS to illustrate information graphically about cars, car dealers, incentives, etc., sometimes neatly packaging them into directives for easy re-use when the case fit. He also created a wealth of customizations and extensions of DimpleJS which allowed for rapid development without sacrificing visualization quality.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; float: left; text-align: center;&#34;&gt;&lt;b&gt;&lt;img height=&#34;155&#34; id=&#34;docs-internal-guid-adf4efb0-1939-cb73-eb4e-29fafe866ac4&#34; src=&#34;/blog/2016/12/client-case-study-carjojo/image-4.png&#34; style=&#34;-webkit-transform: rotate(0.00rad); border: none; transform: rotate(0.00rad);&#34; width=&#34;155&#34;/&gt;&lt;/b&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Josh Williams:&lt;/strong&gt; Python API development. Josh led the efforts in connecting the database into Django and Python to process and aggregate the data as needed. He also used TastyPie to format the API response and created authentication structures for the API.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; float: right; text-align: center;&#34;&gt;&lt;img height=&#34;279&#34; id=&#34;docs-internal-guid-adf4efb0-1941-c6b8-7c03-547234b8105c&#34; src=&#34;/blog/2016/12/client-case-study-carjojo/image-5.png&#34; style=&#34;border: medium none; transform: rotate(0rad);&#34; width=&#34;309&#34;/&gt; &lt;/div&gt;
&lt;h3 id=&#34;project-specifics&#34;&gt;Project Specifics&lt;/h3&gt;
&lt;h4 id=&#34;api-tools&#34;&gt;API Tools&lt;/h4&gt;
&lt;p&gt;Carjojo’s project makes use of some of the best tools on the market today for accessing and displaying data. &lt;a href=&#34;https://www.djangoproject.com/&#34;&gt;Django&lt;/a&gt; and &lt;a href=&#34;http://tastypieapi.org/&#34;&gt;Tastypie&lt;/a&gt; were chosen to allow for rapid API development and to keep the response time down on the website. In most cases the Django ORM was sufficient for generating queries from the data, though in some cases custom queries were written to better aggregate and filter the data directly within Postgres.&lt;/p&gt;
&lt;p&gt;To use the location information in the database, some GIS location smarts were tied into Tastypie. Location searches tied into &lt;a href=&#34;https://docs.djangoproject.com/en/1.10/ref/contrib/gis/&#34;&gt;GeoDjango&lt;/a&gt; and generated &lt;a href=&#34;http://postgis.net/&#34;&gt;PostGIS&lt;/a&gt; queries in the database.&lt;/p&gt;
&lt;h4 id=&#34;front-end-tools&#34;&gt;Front End Tools&lt;/h4&gt;
&lt;p&gt;&lt;a href=&#34;https://d3js.org/&#34;&gt;D3&lt;/a&gt; is standard in data-visualization and is great for doing both simple and complicated graphics. Many of Carjojo’s graphs were bar graphs, pie charts and didn’t really require writing out D3 by hand. We also wanted to make many of them reusable and dynamic (often based on search terms or inputs) with use of Angular directives and services. This could have been done with pure D3, but Dimple makes creating simple D3 graphs easy and fast.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://dimplejs.org/&#34;&gt;DimpleJS&lt;/a&gt; was used a lot in this project. Since Carjojo is data-driven, they wanted to display their information in an aesthetically pleasing manner and DimpleJS allowed us to quickly spin up information against some of the project’s tightest deadlines.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;span id=&#34;docs-internal-guid-adf4efb0-192c-c5d7-47f8-c173ae3b292c&#34; style=&#39;background-color: transparent; color: black; font-family: &#34;arial&#34;; font-size: 14.6667px; font-style: normal; font-variant: normal; font-weight: 400; margin-left: 1em; margin-right: 1em; text-decoration: none; vertical-align: baseline;&#39;&gt;&lt;img height=&#34;120&#34; src=&#34;/blog/2016/12/client-case-study-carjojo/image-6.png&#34; style=&#34;border: medium none; transform: rotate(0rad);&#34; width=&#34;356&#34;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;The approach worked well for most cases. However, sometimes Carjojo wanted something slightly different than what DimpleJS does out of the box. One example of DimpleJS customization work can be found &lt;a href=&#34;/blog/2015/10/intro-to-dimplejs-graphing-in-6-easy/&#34;&gt;here on our blog&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Another thing to note about the data visualizations was that sometimes when the data was plotted and graphed, it brought to light some discrepancies in the back-end calculations and analytics, requiring some back-and-forth between the Carjojo DBA and End Point.&lt;/p&gt;
&lt;h3 id=&#34;results&#34;&gt;Results&lt;/h3&gt;
&lt;p&gt;Carjojo had a successful launch of their service in the summer of 2016. Their system has robust user capabilities, a modern clean design, and a solid platform to grow from. The best news for Carjojo is that now the project has been turned back over to them for development. End Point believes in empowering our clients to move forward with their business and goals without us. Carjojo knows that we’ll be here for support if they need it.&lt;/p&gt;
&lt;img height=&#34;491&#34; id=&#34;docs-internal-guid-adf4efb0-192c-4e5e-97ff-690dabfbb0ec&#34; src=&#34;/blog/2016/12/client-case-study-carjojo/image-7.png&#34; style=&#34;border: medium none; transform: rotate(0rad);&#34; width=&#34;640&#34;/&gt;

      </content>
    </entry>
  
    <entry>
      <title>Case Study: Responsive Design Return on Investment</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2016/07/case-study-responsive-design-return-on/"/>
      <id>https://www.endpointdev.com/blog/2016/07/case-study-responsive-design-return-on/</id>
      <published>2016-07-21T00:00:00+00:00</published>
      <author>
        <name>Elizabeth Garrett Christensen</name>
      </author>
      <content type="html">
        &lt;p&gt;Responsive design has been a hot topic in the e-commerce world for several years now. End Point has worked on many sites over the last few years to transition clients to a responsive design website model. While many large sized retailers have already transitioned to a responsive design, there are many smaller e-commerce sites that are still on an older design model and I would like to show that the return on investment for those stores is still noteworthy.&lt;/p&gt;
&lt;p&gt;The lead of our Interchange team, Greg Hanson, led a responsive design project and I’d like to summarize that work on our blog. For confidentiality, I am leaving out the client’s name in this case.&lt;/p&gt;
&lt;h3 id=&#34;why-go-responsive&#34;&gt;Why Go Responsive?&lt;/h3&gt;
&lt;p&gt;There are two main reasons every e-commerce website, even a small one, needs to become responsive:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Your customers&lt;/li&gt;
&lt;li&gt;Google&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The march toward mobile sales at this point is undeniable and unstoppable. As more and more people become comfortable using their phones and tablets to purchase things, the bigger this market share will become. Also, Google has begun de-prioritizing websites that do not cater to mobile users. If you are waiting to go responsive because of budget, you might surprised to learn how dramatically the mobile revenue increased for the customer in this case.&lt;/p&gt;
&lt;h3 id=&#34;goals&#34;&gt;Goals&lt;/h3&gt;
&lt;p&gt;This client is a small e-commerce business with a heavy ‘on’ season and ‘off’ season where the business owners could focus on this project. They wanted:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;To accommodate the increasing mobile user base; they knew it was there from looking at their Google Analytics.&lt;/li&gt;
&lt;li&gt;To increase revenue from mobile users. They could see that they had a 10% mobile user base, but they were converting only a small percentage.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;end-points-strategy&#34;&gt;End Point’s strategy&lt;/h3&gt;
&lt;p&gt;Our strategy with this small client, to minimize impact to the business and cost was to:&lt;/p&gt;
&lt;h4 id=&#34;use-bootstrap&#34;&gt;Use Bootstrap&lt;/h4&gt;
&lt;p&gt;Bootstrap is one of many front end frameworks that allows you to create a design template and roll that out to all the pages within a website without having to re-code each and every page in a website. This dramatically increases the speed and decreases cost.&lt;/p&gt;
&lt;h4 id=&#34;break-up-the-work-into-segments&#34;&gt;Break up the work into segments&lt;/h4&gt;
&lt;p&gt;In this case, we had a three phase approach:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Phase I, re­design the site using Bootstrap but still at fixed width&lt;/li&gt;
&lt;li&gt;Phase II, site checkout sequence changed to responsive&lt;/li&gt;
&lt;li&gt;Phase III, entire site responsive&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;the-project&#34;&gt;The Project&lt;/h3&gt;
&lt;p&gt;Converting the site to Bootstrap was the biggest chunk of the time and money spent on this project. Since we knew this would be the foundation for the changes to come, we took our time getting it right, keeping the client involved every step of the way. We didn’t want to get in the way of their busy season either, so we completed that project and waited a half a year to begin the next piece.&lt;/p&gt;
&lt;p&gt;The second step was updating checkout sequence to be responsive since this was arguably the hardest part about using the non-responsive site on a mobile device. The client considered this piece top priority. Plus, since it was only a few pages, it allowed us all to better understand the scope of coding the rest of the site and give the client an accurate picture of the budget.&lt;/p&gt;
&lt;p&gt;Last, once we had a responsive checkout sequence, we changed the rest of the internal pages to be responsive and rolled out the entire site as responsive and mobile friendly.&lt;/p&gt;
&lt;h3 id=&#34;results&#34;&gt;Results&lt;/h3&gt;
&lt;p&gt;The first time we looked at the analytics following the responsive conversion, we were &lt;strong&gt;shocked&lt;/strong&gt;! Using a small sample period, from just a year prior, we saw a &lt;strong&gt;280%&lt;/strong&gt; increase in mobile purchases.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2016/07/case-study-responsive-design-return-on/image-0.png&#34; /&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;The timeframe for these comparison numbers was August 2014 before the responsive transition and August of 2015, after the transition.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;To sanity check those numbers, we just re-ran some of the analytics recently and in May of 2016, revenue from mobile users is still up over 90% and &lt;strong&gt;the clients total revenue year-over-year is up 12%&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2016/07/case-study-responsive-design-return-on/image-1.png&#34; /&gt;&lt;/div&gt;
&lt;p&gt;We also ran some numbers on the growth of mobile revenue as a percentage of overall revenue through this process. As you can see, two years ago mobile revenue was less than 1% and is now near 12%.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;img src=&#34;/blog/2016/07/case-study-responsive-design-return-on/image-2.jpeg&#34; /&gt;&lt;/div&gt;
&lt;p&gt;In this case, I didn’t go into all the ways to slice and dice the numbers in Google Analytics. However I&amp;rsquo;m happy to speak with you if you want to know more about mobile users, this client’s data, or how responsive design might help grow your e-commerce business.&lt;/p&gt;
&lt;h3 id=&#34;the-lesson&#34;&gt;The Lesson&lt;/h3&gt;
&lt;p&gt;The lesson here is that any store will benefit from going responsive. Having an experienced partner like End Point that can work with your budget and timeline can make this is a doable project for any size store and budget.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Hue’s on First: How we used responsive bulbs to join software and hardware for a busy medical practice</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2016/03/hues-on-first/"/>
      <id>https://www.endpointdev.com/blog/2016/03/hues-on-first/</id>
      <published>2016-03-14T00:00:00+00:00</published>
      <author>
        <name>Liz Flyntz</name>
      </author>
      <content type="html">
        &lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2016/03/hues-on-first/FastTrackoffice.jpg&#34;/&gt;&lt;/div&gt;
&lt;p&gt;In 2014 we began working with a busy bariatric surgery office in Long Island to create a system that would allow the practice to better manage doctor paging and patient wait time. By placing a responsive, color-coded light bulb and tablet outside each examination room, the staff could see which rooms were empty, which were occupied by a patient waiting on a specific doctor, and in which a doctor-patient consultation was in process. Outside each room is a tablet with information including the patient number, the attending doctor’s name, and the wait time.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2016/03/hues-on-first/FastTrackmapmonitor.jpg&#34;/&gt;&lt;/div&gt;
&lt;p&gt;In addition to providing a comprehensive, granular paging service for doctors, Fast Track also provides feedback to the practice. This feedback includes average patient wait times per doctor, per time of day, and per procedure. This allows the practice to make necessary changes and increase patient satisfaction and peace of mind.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2016/03/hues-on-first/FastTrackapp.jpg&#34;/&gt;&lt;/div&gt;
&lt;p&gt;I asked Danny Divita, one of the main developers on this project, to tell us more about the &lt;a href=&#34;http://www2.meethue.com/en-us/&#34;&gt;Hue&lt;/a&gt;/ &lt;a href=&#34;https://web.archive.org/web/20180107115334/http://www.fasttrackmed.com/&#34;&gt;FastTrack&lt;/a&gt; interface.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;LF: Describe the project for which we used Hue bulbs. What were all the pieces that needed fitting together?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;DD: The Hue bulbs are being used for a bariatric clinic to alert the staff when pages are sent to of pages to specific rooms. Alongside the lights the API also has to work with a RF device-locating API. The RF API had to be coordinated with the Hue light API to coordinate changing colors, alerts, and states.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;LF: Why were Hue bulbs a good solution for the problem of creating an easy-to-understand, integratable visual alert system? Did you consider any alternatives?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;DD: From a cost perspective and ease of integration the bulbs were a good solution for this project. There are other solutions, but they are more costly and the integration would have taken longer.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;LF: How did you hear about Hue bulbs? Was the API easy to access and work with? How was using Hue’s testing environment?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;DD: The client suggested the bulbs during their research before having us develop their application. The API is extremely easy to work with and well documented. The Hue API has a built-in testing feature that made it easy to understand the API and develop around it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;LF: What was the most difficult thing about integrating this technology? Can you think of any other commercial implementations of these bulbs? Specifically in the medical industry?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;DD: The most difficult aspect was trying to come up with a good alert (blinking) feature. The API has some built in alerts, but they are limited to a set timed interval. We had to develop around this to ensure the alerts stayed constant and did not time out. Another application for these lights in the medical field could be to indicate severity of a situation or condition. Because the lights can change color, the applications can signal the proper response for the staff.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;LF: Did you write any new software for this project? Is that work available to other developers?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;DD: We used a third party library that helps to manage stateless workflows. Our application expanded upon this library to design a workflow engine that manages paging the staff, Hue lights, and RF device locating.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Paper Source Case Study with Google Maps API</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/03/paper-source-case-study-with-google/"/>
      <id>https://www.endpointdev.com/blog/2013/03/paper-source-case-study-with-google/</id>
      <published>2013-03-29T00:00:00+00:00</published>
      <author>
        <name>Steph Skardal</name>
      </author>
      <content type="html">
        &lt;img alt=&#34;Basic Google map with location markers&#34; border=&#34;0&#34; src=&#34;/blog/2013/03/paper-source-case-study-with-google/image-0.png&#34;/&gt;
&lt;p&gt;Recently, I’ve been working with the &lt;a href=&#34;https://developers.google.com/maps/&#34;&gt;Google Maps API&lt;/a&gt; for Paper Source, one of our large &lt;a href=&#34;/expertise/perl-interchange/&#34;&gt;Interchange&lt;/a&gt; clients with over 40 physical stores throughout the US.&lt;/p&gt;
&lt;p&gt;On their website, they had previously been managing static HTML pages for these 40 physical stores to share store information, location, and hours. They wanted to move in the direction of something more dynamic with interactive maps. After doing a bit of research on search options out there, I decided to go with the Google Maps API. This article discusses basic implementation of map rendering, search functionality, as well as interesting edge case behavior.&lt;/p&gt;
&lt;h3 id=&#34;basic-map-implementation&#34;&gt;Basic Map Implementation&lt;/h3&gt;
&lt;p&gt;In its most simple form, the markup required for adding a basic map with markers is the shown below. Read more at &lt;a href=&#34;https://developers.google.com/maps/&#34;&gt;Google Maps Documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h5 id=&#34;html&#34;&gt;HTML&lt;/h5&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;map&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h5 id=&#34;css&#34;&gt;CSS&lt;/h5&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;#map {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  height: 500px;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  width: 500px;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h5 id=&#34;javascript&#34;&gt;JavaScript&lt;/h5&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;//mapOptions defined here
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; mapOptions = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  center: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.LatLng(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;40&lt;/span&gt;, -&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;98&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  zoom: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  mapTypeId: google.maps.MapTypeId.ROADMAP
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;//map is the HTML DOM element ID where it will be rendered
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; map = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.Map(&lt;span style=&#34;color:#038&#34;&gt;document&lt;/span&gt;.getElementById(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;map&amp;#34;&lt;/span&gt;), mapOptions);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;//all locations is a JSON object representing locations,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;//where each location has a latitude and longitude
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;$.each(all_locations, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(i, loc) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; marker = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.Marker({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    map: map,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    position: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.LatLng(loc.latitude, loc.longitude)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;building-search-functionality&#34;&gt;Building Search Functionality&lt;/h3&gt;
&lt;img alt=&#34;Search interface: search results are listed on the left, and map with markers is shown on the right&#34; border=&#34;0&#34; src=&#34;/blog/2013/03/paper-source-case-study-with-google/image-1.png&#34; width=&#34;700&#34;/&gt;
&lt;p&gt;Next up, I needed to build out search functionality. Google has its own geocoder to allow address searches. Here is the basic markup for running a search:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; geocoder = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.Geocoder();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;//search is a variable representing the user search, such as a zip code, city name, or state name
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;geocoder.geocode({ &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;address&amp;#39;&lt;/span&gt; : search }, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(results, status) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; search_center = results[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;].geometry.bounds.getCenter();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; mapOptions = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    center: search_center,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zoom: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;10&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    mapTypeId: google.maps.MapTypeId.ROADMAP
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; map = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.Map(&lt;span style=&#34;color:#038&#34;&gt;document&lt;/span&gt;.getElementById(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;map&amp;#34;&lt;/span&gt;), mapOptions);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $.each(all_locations, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(i, loc) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; marker = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.Marker({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      map: map,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      position: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.LatLng(loc.latitude, loc.longitude)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the above code, the search term is passed into the Geocoder object and a map with all locations marked is rendered. To determine which markers are in the visible map boundaries, the following map.getBounds().contains() method would be leveraged:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; visible_locations = [];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$.each(all_locations, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(i, loc) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt;(map.getBounds().contains(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.LatLng(loc.latitude, loc.longitude))) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    visible_locations.push(loc);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;//render visible locations to the left of the map
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;One final step here is to add a listener to the map, so that visible locations are updated when the user zooms in and out. This is accomplished with the following listener:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;google.maps.event.addListener(map, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;zoom_changed&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;//call method to rerender visible locations
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;handling-zero-results&#34;&gt;Handling Zero Results&lt;/h3&gt;
&lt;p&gt;What happens if your Geocoder object can’t find the address? A simple conditional can be used:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;geocoder.geocode({ &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;address&amp;#39;&lt;/span&gt; : search }, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(results, status) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt;(status == &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;ZERO_RESULTS&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;//notify customer that no results have been found
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  } &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;//got results, render location
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;calculate-and-sort-by-distance&#34;&gt;Calculate and Sort by Distance&lt;/h3&gt;
&lt;p&gt;The next layer of logic I needed to add was the ability to determine the distance between the search address and sort the results by distance. To calculate distance, I did some research and settled on the following code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; R = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;6371&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$.each(all_locations, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(i, loc) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; loc_position = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.LatLng(loc.latitude, loc.longitude);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; dLat  = locations.rad(loc.latitude - search_center.lat());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; dLong = locations.rad(loc.longitude - search_center.lng());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;//calculate spherical distance between search position and location
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; a = &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sin(dLat/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;) * &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sin(dLat/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;) +
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.cos(locations.rad(search_center.lat())) *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.cos(locations.rad(search_center.lat())) *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sin(dLong/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;) * &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sin(dLong/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; c = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt; * &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.atan2(&lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sqrt(a), &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sqrt(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;-a));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; d = R * c;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  loc.distance = d;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;//convert distance to miles
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  loc.readable_distance =
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (google.maps.geometry.spherical.computeDistanceBetween(search_center, loc_position) *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0.000621371&lt;/span&gt;).toFixed(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To sort the locations by distance, I leverage jQuery sort:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; sort_by_distance = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(obj) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; obj.sort(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(a, b) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt;(a.distance &amp;gt; b.distance) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; -&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; sorted_locations = sort_by_distance(all_locations);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;adjust-map-boundaries-to-include-specific-markers&#34;&gt;Adjust Map Boundaries to Include Specific Markers&lt;/h3&gt;
&lt;p&gt;Another interesting use case I needed to handle was forcing the map to zoom out to include stores within 100 miles if there was nothing in the initial map boundaries, e.g.:&lt;/p&gt;
&lt;img border=&#34;0&#34; src=&#34;/blog/2013/03/paper-source-case-study-with-google/image-2.png&#34; width=&#34;700&#34;/&gt;
&lt;p&gt;The search for &amp;ldquo;27103&amp;rdquo; doesn’t return any nearby stores, so the map is extended to include stores within 100 miles.&lt;/p&gt;
&lt;p&gt;To accomplish this functionality, I added a bit of code to extend the map boundaries:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;geocoder.geocode({ &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;address&amp;#39;&lt;/span&gt; : search }, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(results, status) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; search_center = results[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;].geometry.bounds.getCenter();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; mapOptions = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    center: search_center,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zoom: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;10&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    mapTypeId: google.maps.MapTypeId.ROADMAP
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; map = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.Map(&lt;span style=&#34;color:#038&#34;&gt;document&lt;/span&gt;.getElementById(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;map&amp;#34;&lt;/span&gt;), mapOptions);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; current_bounds = results[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;].geometry.bounds;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $.each(all_locations, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(i, loc) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; loc_position = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.LatLng(loc.latitude, loc.longitude);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; dLat  = locations.rad(loc.latitude - search_center.lat());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; dLong = locations.rad(loc.longitude - search_center.lng());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;//calculate spherical distance between search position and location
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; a = &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sin(dLat/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;) * &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sin(dLat/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;) +
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.cos(locations.rad(search_center.lat())) *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.cos(locations.rad(search_center.lat())) *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sin(dLong/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;) * &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sin(dLong/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; c = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt; * &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.atan2(&lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sqrt(a), &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sqrt(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;-a));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; d = R * c;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    loc.distance = d;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;//convert distance to miles
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;    loc.readable_distance =
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (google.maps.geometry.spherical.computeDistanceBetween(search_center, loc_position) *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0.000621371&lt;/span&gt;).toFixed(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; marker = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.Marker({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      map: map,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      position: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.LatLng(loc.latitude, loc.longitude)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt;(loc.readable_distance &amp;lt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;100&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      current_bounds.extend(loc_position);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;//Google map method to fit map boundaries to desired boundaries
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  map.fitBounds(current_bounds);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;disable-scroll-and-zoom-on-mobile-sized-devices&#34;&gt;Disable Scroll and Zoom on Mobile-Sized Devices&lt;/h3&gt;
&lt;p&gt;One final behavior needed was to disable map zooming and scrolling on mobile devices, to improve the usability on mobile/touch interfaces. Here’s how this was accomplished:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; options_listener = google.maps.event.addListener(map, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt;($(&lt;span style=&#34;color:#038&#34;&gt;window&lt;/span&gt;).width() &amp;lt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;656&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    map.setOptions({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      draggable: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      zoomControl: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      scrollwheel: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      disableDoubleClickZoom: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      streetViewControl: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  google.maps.event.removeListener(options_listener);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;With all this code, the final location search functionality includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Basic United States map rendering to display all physical store locations.&lt;/li&gt;
&lt;li&gt;Search by location which shows stores within 100 miles, and allows users to zoom in and out to adjust their search. Search lists results sorted by distance.&lt;/li&gt;
&lt;li&gt;“Saved” or “Quick” searches by states, which displays all physical stores by state.&lt;/li&gt;
&lt;li&gt;Adjustment of mobile display map options.&lt;/li&gt;
&lt;/ul&gt;

      </content>
    </entry>
  
    <entry>
      <title>Mobixa: A Client Case Study</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2012/12/mobixa-client-case-study/"/>
      <id>https://www.endpointdev.com/blog/2012/12/mobixa-client-case-study/</id>
      <published>2012-12-05T00:00:00+00:00</published>
      <author>
        <name>Steph Skardal</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;a href=&#34;http://www.mobixa.com/&#34;&gt;&lt;img border=&#34;0&#34; height=&#34;122&#34; src=&#34;/blog/2012/12/mobixa-client-case-study/image-0.png&#34; width=&#34;324&#34;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A few weeks ago we saw the official (and successful!) website launch for one of our clients, &lt;a href=&#34;http://www.mobixa.com/&#34;&gt;Mobixa&lt;/a&gt;. Mobixa will buy back your used iPhones and/or provide you with information about when you should upgrade your existing phone and sell it back. Right now, Mobixa is currently buying back iPhones and advising on iPhones and Androids. End Point has been working with Mobixa for several months now. This article outlines some of the interesting project notes and summarizes End Point’s diverse skillset used for this particular website.&lt;/p&gt;
&lt;h3 id=&#34;initial-framework&#34;&gt;Initial Framework&lt;/h3&gt;
&lt;p&gt;Mobixa initially wanted a an initial proof of concept website without significant investment in development architecture because the long-term plan and success was somewhat unknown at the project unset. The initial framework comprised of basic HTML combined with a bit of logic driven by PHP. After a user submitted their phone information, data was sent to &lt;a href=&#34;http://www.wufoo.com/&#34;&gt;Wufoo&lt;/a&gt; via a Wufoo provided PHP-based API, and data was further handled from Wufoo. Wufoo is an online form builder that has nice export capabilities, and painlessly integrates with MailChimp.&lt;/p&gt;
&lt;p&gt;This initial architecture was suitable for collecting user information, having minimal local database needs and allowing external systems (e.g. Wufoo, MailChimp) to handle much of the user logic. However, it became limiting when the idea of user persistence came into play – the long-term goal will be to allow users to modify previous submissions and look up their order information, essentially a need for basic user account management functionality. For that reason, we made a significant switch in the architecture, described below.&lt;/p&gt;
&lt;h3 id=&#34;framework-2-rails-3&#34;&gt;Framework #2: Rails 3&lt;/h3&gt;
&lt;p&gt;Because of the limiting nature of a database-less application with externally managed data and as business needs for users increased, we decided to make the move to Rails. End Point has a large team of Rails developers, Rails is a suitable framework for developing applications efficiently, and we are experienced in working with Rails plugins such as &lt;a href=&#34;https://github.com/sferik/rails_admin&#34;&gt;RailsAdmin&lt;/a&gt;, &lt;a href=&#34;https://github.com/plataformatec/devise&#34;&gt;Devise&lt;/a&gt;, and &lt;a href=&#34;https://github.com/ryanb/cancan&#34;&gt;CanCan&lt;/a&gt;, which immediately provide a configurable admin interface, user authentication, and user authentication to the application. In the process of moving to Rails, we eliminated the middle-man Wufoo to integrate with the shipping fulfillment center and MailChimp directly.&lt;/p&gt;
&lt;p&gt;The current Mobixa site runs on Rails 3, &lt;a href=&#34;http://nginx.org/&#34;&gt;Nginx&lt;/a&gt; and &lt;a href=&#34;http://unicorn.bogomips.org/&#34;&gt;Unicorn&lt;/a&gt; backed by PostgreSQL, leverages End Point’s &lt;a href=&#34;http://www.devcamps.org/&#34;&gt;DevCamps&lt;/a&gt; to allow multiple developers to simultaneously add features and maintain the site painlessly, and uses RailsAdmin, Devise, and CanCan. It features a responsive design and uses advanced jQuery techniques. The focus of the site is still a simple HTML page that passes user-entered information to the local database, but several user management features have been added as well as the ability to sell back multiple phones at a time.&lt;/p&gt;
&lt;h3 id=&#34;mailchimp-integration&#34;&gt;MailChimp Integration&lt;/h3&gt;
&lt;p&gt;In my search for a decent Rails MailChimp integration gem, I found &lt;a href=&#34;https://github.com/amro/gibbon&#34;&gt;gibbon&lt;/a&gt;. Gibbon is fairly simple - it’s an API wrapper for interacting with MailChimp. Any API capabilities and methods available in MailChimp can be called via Gibbon. The integration looks something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# user model&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;update_mailchimp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  gb = &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Gibbon&lt;/span&gt;.new(*api_key*, { &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:timeout&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;30&lt;/span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  info = gb.list_member_info({ &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:id&lt;/span&gt; =&amp;gt; *list_id*, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:email_address&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#038&#34;&gt;self&lt;/span&gt;.email })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; info[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;success&amp;#34;&lt;/span&gt;] == &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gb.listUpdateMember({ &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:id&lt;/span&gt; =&amp;gt; *list_id*,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:email_address&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#038&#34;&gt;self&lt;/span&gt;.email,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:merge_vars&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#038&#34;&gt;self&lt;/span&gt;.mailchimp_data })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gb.list_subscribe({ &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:id&lt;/span&gt; =&amp;gt; *list_id*,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:email_address&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#038&#34;&gt;self&lt;/span&gt;.email,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#888&#34;&gt;# additional new user arguments #&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:merge_vars&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#038&#34;&gt;self&lt;/span&gt;.mailchimp_data })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The above method instantiates a connection to Mailchimp and checks if the user is already subscribed to the Mailchimp list. If the user is subscribed, the listUpdateMember method is called to update the user subscription information. Otherwise, list_subscribe is called to add the user to the Mailchimp list.&lt;/p&gt;
&lt;h3 id=&#34;whats-next&#34;&gt;What’s Next?&lt;/h3&gt;
&lt;p&gt;In addition to expanding the product buyback capabilities, we expect to integrate additional features such as external-API driven address verification, social media integration, referral management, and more advanced user account management features. The project will continue to involve various members of our team such as &lt;a href=&#34;/team/richard-templet/&#34;&gt;Richard&lt;/a&gt;, &lt;a href=&#34;/team/greg-davidson/&#34;&gt;Greg D.&lt;/a&gt;, Tim Case, &lt;a href=&#34;/blog/authors/kamil-ciemniewski/&#34;&gt;Kamil&lt;/a&gt;, &lt;a href=&#34;/team/josh-williams/&#34;&gt;Josh W.&lt;/a&gt; and me.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>College District launches 4 additional sites</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2009/01/college-district-launches-4-additional/"/>
      <id>https://www.endpointdev.com/blog/2009/01/college-district-launches-4-additional/</id>
      <published>2009-01-22T00:00:00+00:00</published>
      <author>
        <name>Ron Phipps</name>
      </author>
      <content type="html">
        &lt;p&gt;We built a system for one of our clients, College District, that allows them to launch e-commerce sites fairly easily using a shared framework, database and adminstration panel. The first of the sites, &lt;a href=&#34;http://www.tigerdistrict.com&#34;&gt;Tiger District&lt;/a&gt;, launched over a year ago and has been succesful in selling LSU branded merchandise. A few weeks ago the following sites were launched on the system: &lt;a href=&#34;https://web.archive.org/web/20100117102538/http://www.soonerdistrict.com/&#34;&gt;Sooner District&lt;/a&gt;, &lt;a href=&#34;https://web.archive.org/web/20090310025851/http://www.longhorndistrict.com/&#34;&gt;Longhorn District&lt;/a&gt;, &lt;a href=&#34;https://web.archive.org/web/20090131142328/http://www.gatordistrict.com/&#34;&gt;Gator District&lt;/a&gt; and &lt;a href=&#34;http://www.rolltidedistrict.com&#34;&gt;Roll Tide District&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The interesting parts of the system include a single Interchange installation, serving two catalogs, one for the administration area and one for all of the stores. Each site gets its own htdocs area for its images and CSS files (which are generated by the site generator using the selected colors). A cool part about this setup is that a new feature added appears on all sites instantly. The site code uses the request domain name to determine which user to connect to the database as. The heavy lifting of the multi-site capbilities is handled by a single Postgres database which utilizes roles, schemas and search paths to show or hide data based on the user that connected to the database. This works really well when it comes time to makes changes to an underlying table, instead of having to update the same table in 10 different databases, the change is applied to a single table and all sites are effected by the change.&lt;/p&gt;
&lt;p&gt;Additional sites will be launched in the near future as well as some great community features soon.&lt;/p&gt;

      </content>
    </entry>
  
</feed>
