diff --git a/common/static/sass/edx-pattern-library-shims/_buttons.scss b/common/static/sass/edx-pattern-library-shims/_buttons.scss
index 08eb3361dd709dd10c2865b9a7215c8a552b98a9..19bcdea1e9f955b03650fbb359086cc66f90ba0d 100644
--- a/common/static/sass/edx-pattern-library-shims/_buttons.scss
+++ b/common/static/sass/edx-pattern-library-shims/_buttons.scss
@@ -10,6 +10,8 @@
 // ----------------------------
 %btn-shims {
   display: inline-block;
+  background-color: transparent;
+  background-image: none;
   border-style: $btn-border-style;
   border-radius: $btn-border-radius;
   border-width: $btn-border-size;
diff --git a/lms/djangoapps/courseware/date_summary.py b/lms/djangoapps/courseware/date_summary.py
index 2e0b2dc007229296a638cfcf2b30d84b3d527bb4..c0b552659cdfecf16d28d18a371f5298aedb9372 100644
--- a/lms/djangoapps/courseware/date_summary.py
+++ b/lms/djangoapps/courseware/date_summary.py
@@ -118,6 +118,14 @@ class DateSummary(object):
             return datetime.now(utc) <= self.date
         return False
 
+    def deadline_has_passed(self):
+        """
+        Return True if a deadline (the date) exists, and has already passed.
+        Returns False otherwise.
+        """
+        deadline = self.date
+        return deadline is not None and deadline <= datetime.now(utc)
+
     def __repr__(self):
         return u'DateSummary: "{title}" {date} is_enabled={is_enabled}'.format(
             title=self.title,
@@ -313,13 +321,6 @@ class VerificationDeadlineDate(DateSummary):
         """Return the verification status for this user."""
         return SoftwareSecurePhotoVerification.user_status(self.user)[0]
 
-    def deadline_has_passed(self):
-        """
-        Return True if a verification deadline exists, and has already passed.
-        """
-        deadline = self.date
-        return deadline is not None and deadline <= datetime.now(utc)
-
     def must_retry(self):
         """Return True if the user must re-submit verification, False otherwise."""
         return self.verification_status == 'must_reverify'
diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py
index f186277f7148dcb1cfa4453df1092f2bfecb1d42..5c8fdce518e22e2ef2ee0d528b9d30d7b7821156 100644
--- a/lms/djangoapps/courseware/tests/test_views.py
+++ b/lms/djangoapps/courseware/tests/test_views.py
@@ -209,8 +209,8 @@ class IndexQueryTestCase(ModuleStoreTestCase):
     NUM_PROBLEMS = 20
 
     @ddt.data(
-        (ModuleStoreEnum.Type.mongo, 10, 147),
-        (ModuleStoreEnum.Type.split, 4, 147),
+        (ModuleStoreEnum.Type.mongo, 10, 149),
+        (ModuleStoreEnum.Type.split, 4, 149),
     )
     @ddt.unpack
     def test_index_query_counts(self, store_type, expected_mongo_query_count, expected_mysql_query_count):
diff --git a/lms/djangoapps/courseware/views/index.py b/lms/djangoapps/courseware/views/index.py
index 9709c6ad501a2df27b2e05a75cbe1dc7050073cd..62e8593081a2a75f755a0e18fec2cd7d522420cd 100644
--- a/lms/djangoapps/courseware/views/index.py
+++ b/lms/djangoapps/courseware/views/index.py
@@ -33,6 +33,7 @@ from openedx.core.djangoapps.user_api.preferences.api import get_user_preference
 from openedx.core.djangoapps.waffle_utils import WaffleSwitchNamespace
 from openedx.features.course_experience import UNIFIED_COURSE_VIEW_FLAG, default_course_url_name
 from openedx.features.enterprise_support.api import data_sharing_consent_required
+from openedx.features.course_experience.views.course_sock import CourseSockFragmentView
 from request_cache.middleware import RequestCache
 from shoppingcart.models import CourseRegistrationCode
 from student.views import is_course_blocked
@@ -367,6 +368,9 @@ class CoursewareIndex(View):
             table_of_contents['chapters'],
         )
 
+        courseware_context['course_sock_fragment'] = CourseSockFragmentView().render_to_fragment(
+            request, course=self.course)
+
         # entrance exam data
         self._add_entrance_exam_to_context(courseware_context)
 
diff --git a/lms/static/sass/_build-course.scss b/lms/static/sass/_build-course.scss
index d073a2c27b84767e678b14a69add5b747b29dfec..c23b8dad174ebb8b23d4062e69e4e8172344e480 100644
--- a/lms/static/sass/_build-course.scss
+++ b/lms/static/sass/_build-course.scss
@@ -68,3 +68,6 @@
 
 // responsive
 @import 'base/layouts'; // temporary spot for responsive course
+
+// features
+@import 'features/course-sock';
diff --git a/lms/static/sass/_build-lms-v2.scss b/lms/static/sass/_build-lms-v2.scss
index 3c1e078fdc6b308bd01bfb76e292c7b0a692d969..595cfd354296e4765112e16eea8f881825e05181 100644
--- a/lms/static/sass/_build-lms-v2.scss
+++ b/lms/static/sass/_build-lms-v2.scss
@@ -27,3 +27,4 @@
 @import 'features/bookmarks';
 @import 'features/course-experience';
 @import 'features/course-search';
+@import 'features/course-sock';
diff --git a/lms/static/sass/features/_course-experience.scss b/lms/static/sass/features/_course-experience.scss
index 0337bf41d3da382487a057db32172195c8cafd08..a702fe5858447b5d4353a1257f8db8381da695a4 100644
--- a/lms/static/sass/features/_course-experience.scss
+++ b/lms/static/sass/features/_course-experience.scss
@@ -107,6 +107,10 @@
             border: 1px solid $lms-active-color;
           }
         }
+
+        &:last-child {
+          border-bottom: none;
+        }
       }
     }
   }
@@ -186,4 +190,3 @@
     }
   }
 }
-
diff --git a/lms/static/sass/features/_course-sock.scss b/lms/static/sass/features/_course-sock.scss
new file mode 100644
index 0000000000000000000000000000000000000000..a457033a451877f8955fa3f0120ca9bcb1928223
--- /dev/null
+++ b/lms/static/sass/features/_course-sock.scss
@@ -0,0 +1,180 @@
+.verification-sock {
+  display: inline-block;
+  position: relative;
+  width: 100%;
+  margin-top: $baseline;
+  max-width: $lms-max-width;
+  margin: $baseline auto 0;
+  -webkit-transition: all 0.4s ease-out;
+  -moz-transition: all 0.4s ease-out;
+  -o-transition: all 0.4s ease-out;
+  -ms-transition: all 0.4s ease-out;
+  transition: all 0.4s ease-out;
+
+  .action-toggle-verification-sock {
+    @include left(50%);
+    @include margin-left(-1 * $baseline * 15/2);
+    position: absolute;
+    top: (-1 * $baseline);
+    width: ($baseline * 15);
+    color: $button-bg-hover-color;
+    background-color: $success-color;
+    border-color: $success-color;
+    background-image: none;
+    box-shadow: none;
+    -webkit-transition: background-color 0.5s;
+    transition: background-color 0.5s;
+
+    &.active {
+      color: $success-color;
+      background-color: $button-bg-hover-color;
+      border-color: $success-color;
+      background-image: none;
+      box-shadow: none;
+
+      &:hover {
+        color: $button-bg-hover-color;
+        background-color: $success-color-hover;
+        border-color: $success-color-hover;
+        background-image: none;
+        box-shadow: none;
+      }
+    }
+
+    &:hover {
+      color: $button-bg-hover-color;
+      background-color: $success-color-hover;
+      border-color: $success-color-hover;
+      background-image: none;
+      box-shadow: none;
+    }
+  }
+
+  .verification-main-panel {
+    display: none;
+    overflow: hidden;
+    border-top: 1px solid $lms-border-color;
+    padding: ($baseline * 5/2) ($baseline * 2);
+    -webkit-transition: height ease-out;
+    transition: height ease-out;
+
+    .verification-desc-panel {
+      color: $black-t3;
+      position: relative;
+
+      @media (max-width: 960px) {
+        .mini-cert {
+          display: none;
+          border: 1px solid $black-t0;
+        }
+      }
+
+      .mini-cert {
+        @include right($baseline);
+        position: absolute;
+        top: $baseline;
+        width: ($baseline * 13);
+      }
+
+      h2 {
+        font-size: 1.5rem;
+        font-weight: 700;
+      }
+
+      h4 {
+        font-size: 1.25rem;
+        font-weight: 600;
+      }
+
+      .learner-story-container {
+        display: flex;
+        max-width: 630px;
+
+        .student-image {
+          margin: ($baseline / 4) $baseline 0 0;
+          height: ($baseline * 5/2);
+          width: ($baseline * 5/2);
+        }
+
+        .story-quote > .author{
+          display: block;
+          margin-top: ($baseline / 4);
+          font-weight: 600;
+        }
+
+        &:not(:first-child) {
+          margin-top: ($baseline * 2);
+        }
+      }
+
+      .action-upgrade-certificate {
+        position: absolute;
+        right: $baseline;
+        background-color: $success-color;
+        border-color: $success-color;
+        background-image: none;
+        box-shadow: none;
+
+        @media (max-width: 960px) {
+          & {
+            position: relative;
+            margin-top: ($baseline * 2);
+          }
+        }
+
+        @media (min-width: 960px) {
+          &.stuck-top {
+            bottom: auto;
+            top: $baseline * (52 / 5);
+          }
+
+          &.stuck-bottom {
+            top: auto;
+            bottom: $baseline * (-1 * 3/2);
+          }
+
+          &.attached {
+            @include right($baseline);
+            position: fixed;
+            bottom: $baseline;
+            top: auto;
+          }
+        }
+
+        &:hover {
+          background-color: $success-color-hover;
+          border-color: $success-color-hover;
+        }
+      }
+    }
+  }
+}
+
+// Overrides for the courseware page.
+.view-courseware {
+  .verification-sock {
+    margin-top: 0;
+    border-top: none;
+    border-bottom: none;
+
+    .action-toggle-verification-sock {
+      top: (-1 * $baseline * 5/4);
+
+      &:not(.active) {
+        color: $button-bg-hover-color;
+        background-color: $success-color;
+        box-shadow: none;
+        border: 1px solid $success-color;
+
+        &:hover {
+          background-color: $success-color-hover;
+        }
+      }
+    }
+
+    .verification-main-panel {
+      border-top: 0;
+      border-bottom: 1px solid $lms-border-color;
+    }
+  }
+}
diff --git a/lms/static/sass/partials/base/_variables.scss b/lms/static/sass/partials/base/_variables.scss
index 76becc6145fffea5db97d801da50a498a0535e3d..00aa6d412f49434fdab2e9799525dea0df8edf67 100644
--- a/lms/static/sass/partials/base/_variables.scss
+++ b/lms/static/sass/partials/base/_variables.scss
@@ -36,7 +36,7 @@ $fg-gutter: $gw-gutter !default;
 $fg-max-columns: 12 !default;
 $fg-max-width: 1400px !default;
 $fg-min-width: 810px !default;
-
+$lms-max-width: 1180px !default;
 
 // ----------------------------
 // #COLORS
@@ -218,7 +218,7 @@ $active-color: $blue !default;
 $highlight-color: rgb(255,255,0) !default;
 $alert-color: rgb(212, 64, 64) !default;
 $success-color: rgb(0, 155, 0) !default;
-
+$success-color-hover: rgb(0, 129, 0) !default;
 
 // ----------------------------
 // #COLORS- EDX-SPECIFIC
diff --git a/lms/static/sass/shared-v2/_variables.scss b/lms/static/sass/shared-v2/_variables.scss
index 503efd066bb7e5f7f96116fac98c3a2ca632783b..34a2cd7b9ae795719e1a4031421dfe20a0080aa4 100644
--- a/lms/static/sass/shared-v2/_variables.scss
+++ b/lms/static/sass/shared-v2/_variables.scss
@@ -9,27 +9,38 @@
 // ----------------------------
 // #GRID
 // ----------------------------
-$lms-max-width: 1180px;
+$lms-max-width: 1180px !default;
 
 // ----------------------------
 // #COLORS
 // ----------------------------
-$lms-gray: palette(grayscale, base);
-$lms-background-color: palette(grayscale, x-back);
-$lms-container-background-color: $white;
-$lms-border-color: palette(grayscale, back);
-$lms-label-color: palette(grayscale, black);
-$lms-active-color: palette(primary, base);
-$lms-preview-menu-color: #c8c8c8;
 
-$white-transparent: rgba(255, 255, 255, 0);
-$white-opacity-40: rgba(255, 255, 255, 0.4);
-$white-opacity-60: rgba(255, 255, 255, 0.6);
-$white-opacity-70: rgba(255, 255, 255, 0.7);
-$white-opacity-80: rgba(255, 255, 255, 0.8);
+$lms-gray: palette(grayscale, base) !default;
+$lms-background-color: palette(grayscale, x-back) !default;
+$lms-container-background-color: $white !default;
+$lms-border-color: palette(grayscale, back) !default;
+$lms-label-color: palette(grayscale, black) !default;
+$lms-active-color: palette(primary, base) !default;
+$lms-preview-menu-color: #c8c8c8 !default;
+$success-color: palette(success, accent) !default;
+$success-color-hover: palette(success, text) !default;
 
-$light-grey-transparent: rgba(200,200,200, 0);
-$light-grey-solid: rgba(200,200,200, 1);
+$button-bg-hover-color: $white !default;
+
+$white-transparent: rgba(255, 255, 255, 0) !default;
+$white-opacity-40: rgba(255, 255, 255, 0.4) !default;
+$white-opacity-60: rgba(255, 255, 255, 0.6) !default;
+$white-opacity-70: rgba(255, 255, 255, 0.7) !default;
+$white-opacity-80: rgba(255, 255, 255, 0.8) !default;
+
+$black:     rgb(0,0,0) !default;
+$black-t0:  rgba($black, 0.125) !default;
+$black-t1:  rgba($black, 0.25) !default;
+$black-t2:  rgba($black, 0.5) !default;
+$black-t3:  rgba($black, 0.75) !default;
+
+$light-grey-transparent: rgba(200,200,200, 0) !default;
+$light-grey-solid: rgba(200,200,200, 1) !default;
 
 // ----------------------------
 // #TYPOGRAPHY
@@ -42,9 +53,10 @@ $font-bold: 700 !default;
 // ----------------------------
 // #ICONS
 // ----------------------------
-$lms-dark-icon-color: $white;
-$lms-dark-icon-background-color: palette(grayscale, black);
+// Icons
+$lms-dark-icon-color: $white !default;
+$lms-dark-icon-background-color: palette(grayscale, black) !default;
 
-$site-status-color: rgb(182,37,103);
+$site-status-color: rgb(182,37,103) !default;
 
 $shadow-l1: rgba(0,0,0,0.1) !default;
diff --git a/lms/templates/courseware/courseware.html b/lms/templates/courseware/courseware.html
index b7e9ed4e8cb370fb111c3d70a9305f2e6d5c1288..08973de4390ea10dd996fc421ec7a9440619a578 100644
--- a/lms/templates/courseware/courseware.html
+++ b/lms/templates/courseware/courseware.html
@@ -226,6 +226,7 @@ ${HTML(fragment.foot_html())}
     </section>
 
   </div>
+  ${HTML(course_sock_fragment.body_html())}
 </div>
 <div class="container-footer">
   % if settings.FEATURES.get("LICENSING", False):
diff --git a/openedx/features/course_experience/__init__.py b/openedx/features/course_experience/__init__.py
index 795b329138115b8edce1c174fb4d59a96eb94e65..2fa75ecee2e0a6cf56309a48698b3abcb8ec28f6 100644
--- a/openedx/features/course_experience/__init__.py
+++ b/openedx/features/course_experience/__init__.py
@@ -19,6 +19,9 @@ WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace(name='course_experience')
 # Waffle flag to enable a single unified "Course" tab.
 UNIFIED_COURSE_TAB_FLAG = CourseWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'unified_course_tab')
 
+# Waffle flag to enable the sock on the footer of the home and courseware pages
+DISPLAY_COURSE_SOCK = CourseWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'display_course_sock')
+
 
 def course_home_page_title(course):  # pylint: disable=unused-argument
     """
diff --git a/openedx/features/course_experience/static/course_experience/images/learner-quote.png b/openedx/features/course_experience/static/course_experience/images/learner-quote.png
new file mode 100644
index 0000000000000000000000000000000000000000..46918fa92b59f1afc4f6d86f8002a27a7d4015a2
Binary files /dev/null and b/openedx/features/course_experience/static/course_experience/images/learner-quote.png differ
diff --git a/openedx/features/course_experience/static/course_experience/images/learner-quote2.png b/openedx/features/course_experience/static/course_experience/images/learner-quote2.png
new file mode 100644
index 0000000000000000000000000000000000000000..b73d71a7732d8ea30f1cde73ef7c5f7dd52de48d
Binary files /dev/null and b/openedx/features/course_experience/static/course_experience/images/learner-quote2.png differ
diff --git a/openedx/features/course_experience/static/course_experience/images/verified-cert.png b/openedx/features/course_experience/static/course_experience/images/verified-cert.png
new file mode 100644
index 0000000000000000000000000000000000000000..79a661a69c7ad3dd8b13f0263ae9e78614a67721
Binary files /dev/null and b/openedx/features/course_experience/static/course_experience/images/verified-cert.png differ
diff --git a/openedx/features/course_experience/static/course_experience/js/CourseSock.js b/openedx/features/course_experience/static/course_experience/js/CourseSock.js
new file mode 100644
index 0000000000000000000000000000000000000000..f654694fe21375347e573d4c663a31d5ba8e4865
--- /dev/null
+++ b/openedx/features/course_experience/static/course_experience/js/CourseSock.js
@@ -0,0 +1,79 @@
+/* globals Logger */
+
+export class CourseSock {  // eslint-disable-line import/prefer-default-export
+  constructor() {
+    const $toggleActionButton = $('.action-toggle-verification-sock');
+    const $verificationSock = $('.verification-sock .verification-main-panel');
+    const $upgradeToVerifiedButton = $('.verification-sock .action-upgrade-certificate');
+    const pageLocation = window.location.href.indexOf('courseware') > -1
+        ? 'Course Content Page' : 'Home Page';
+
+    // Behavior to fix button to bottom of screen on scroll
+    const fixUpgradeButton = () => {
+      if (!$upgradeToVerifiedButton.is(':visible')) return;
+
+      // Grab the current scroll location
+      const documentBottom = $(window).scrollTop() + $(window).height();
+
+      // Establish a sliding window in which the button is fixed
+      const startFixed = $verificationSock.offset().top + 320;
+      const endFixed = (startFixed + $verificationSock.height()) - 220;
+
+      // Assure update button stays in sock even when max-width is exceeded
+      const distLeft = ($verificationSock.offset().left + $verificationSock.width())
+        - ($upgradeToVerifiedButton.width() + 22);
+
+      // Update positioning when scrolling is in fixed window and screen width is sufficient
+      if ((documentBottom > startFixed && documentBottom < endFixed)
+          || $(window).width() < 960) {
+        $upgradeToVerifiedButton.addClass('attached');
+        $upgradeToVerifiedButton.css('left', `${distLeft}px`);
+      } else {
+        // If outside sliding window, reset to un-attached state
+        $upgradeToVerifiedButton.removeClass('attached');
+        $upgradeToVerifiedButton.css('left', 'auto');
+
+        // Add class to define absolute location
+        if (documentBottom < startFixed) {
+          $upgradeToVerifiedButton.addClass('stuck-top');
+          $upgradeToVerifiedButton.removeClass('stuck-bottom');
+        } else if (documentBottom > endFixed) {
+          $upgradeToVerifiedButton.addClass('stuck-bottom');
+          $upgradeToVerifiedButton.removeClass('stuck-top');
+        }
+      }
+    };
+
+    // Fix the sock to the screen on scroll and resize events
+    if ($upgradeToVerifiedButton.length) {
+      $(window).scroll(fixUpgradeButton).resize(fixUpgradeButton);
+    }
+
+    // Open the sock when user clicks to Learn More
+    $toggleActionButton.on('click', () => {
+      const toggleSpeed = 400;
+      $toggleActionButton.toggleClass('active').toggleClass('aria-expanded');
+      $verificationSock.slideToggle(toggleSpeed, fixUpgradeButton);
+
+      // Log open and close events
+      const isOpening = $toggleActionButton.hasClass('active');
+      const logMessage = isOpening ? 'User opened the verification sock.'
+          : 'User closed the verification sock.';
+      Logger.log(
+        logMessage,
+        {
+          from_page: pageLocation,
+        },
+      );
+    });
+
+    $upgradeToVerifiedButton.on('click', () => {
+      Logger.log(
+        'User clicked the upgrade button in the verification sock.',
+        {
+          from_page: pageLocation,
+        },
+      );
+    });
+  }
+}
diff --git a/openedx/features/course_experience/templates/course_experience/course-home-fragment.html b/openedx/features/course_experience/templates/course_experience/course-home-fragment.html
index 85ce1b1bd95e10824319c0d79c90920ce336b651..5aa13184aefe07d4886ef60020a51264683bfcf0 100644
--- a/openedx/features/course_experience/templates/course_experience/course-home-fragment.html
+++ b/openedx/features/course_experience/templates/course_experience/course-home-fragment.html
@@ -97,5 +97,6 @@ from openedx.features.course_experience import UNIFIED_COURSE_TAB_FLAG
             </aside>
         </div>
     </div>
+    ${HTML(course_sock_fragment.body_html())}
 </div>
 </%block>
diff --git a/openedx/features/course_experience/templates/course_experience/course-sock-fragment.html b/openedx/features/course_experience/templates/course_experience/course-sock-fragment.html
new file mode 100644
index 0000000000000000000000000000000000000000..9b3f89b5995457f18f5544971b2137683562560d
--- /dev/null
+++ b/openedx/features/course_experience/templates/course_experience/course-sock-fragment.html
@@ -0,0 +1,69 @@
+## mako
+
+<%page expression_filter="h"/>
+<%namespace name='static' file='../static_content.html'/>
+
+<%!
+from openedx.core.djangolib.markup import HTML
+from openedx.features.course_experience import DISPLAY_COURSE_SOCK
+%>
+
+<%block name="content">
+    % if show_course_sock and DISPLAY_COURSE_SOCK.is_enabled(course_id):
+    <div class="verification-sock">
+        <button type="button" class="btn btn-brand focusable action-toggle-verification-sock">
+            Learn About Verified Certificate
+        </button>
+        <div class="verification-main-panel">
+            <div class="verification-desc-panel content-main">
+                <h2>edX Verified Certificate</h2>
+                <h4>Why upgrade?</h4>
+                <ul>
+                    <li>Official proof of completion</li>
+                    <li>Easily shareable certificate</li>
+                    <li>Proven motivator to complete the course</li>
+                    <li>Certificate purchases help edX continue to offer free courses</li>
+                </ul>
+                <h4>How it works</h4>
+                <ul>
+                    <li>Pay the Verified Certificate upgrade fee</li>
+                    <li>Verify your identity with a webcam and government-issued ID</li>
+                    <li>Study hard and pass the course</li>
+                    <li>Share your certificate with friends, employers, and others</li>
+                </ul>
+                <h4>edX Learner Stories</h4>
+                <div class="learner-story-container">
+                    <img class="student-image" alt="Student Image" src="${static.url('course_experience/images/learner-quote.png')}" />
+                    <div class="story-quote">
+                        My certificate has helped me showcase my knowledge on my
+                        resume - I feel like this certificate could really help me land
+                        my dream job!
+                        <span class="author">- Christina Fong, edX Learner</span>
+                    </div>
+                </div>
+                <div class="learner-story-container">
+                    <img class="student-image" alt="Student Image" src="${static.url('course_experience/images/learner-quote2.png')}" />
+                    <div class="story-quote">
+                        I wanted to include a verified certificate on my resume and my profile to
+                        illustrate that I am working towards this goal I have and that I have
+                        achieved something while I was unemployed.</br>
+                        <span class="author">- Cheryl Troell, edX Learner</span>
+                    </div>
+                </div>
+                <img class="mini-cert" src="${static.url('course_experience/images/verified-cert.png')}"/>
+                <a href="/verify_student/upgrade/${course_id}/">
+                    <button type="button" class="btn btn-brand stuck-top focusable action-upgrade-certificate">
+                        Upgrade Now (${HTML(course_price)})
+                    </button>
+                </a>
+            </div>
+        </div>
+    </div>
+    % endif
+</%block>
+
+<%static:webpack entry="CourseSock">
+    new CourseSock({
+        el:'.verification-sock'
+    });
+</%static:webpack>
diff --git a/openedx/features/course_experience/tests/views/test_course_home.py b/openedx/features/course_experience/tests/views/test_course_home.py
index 9b4eaee9ef38b83e74bacc3fbab44ee52c73595e..491afbe37d1089c874b57ad465269179b7167e18 100644
--- a/openedx/features/course_experience/tests/views/test_course_home.py
+++ b/openedx/features/course_experience/tests/views/test_course_home.py
@@ -89,7 +89,7 @@ class TestCourseHomePage(SharedModuleStoreTestCase):
         course_home_url(self.course)
 
         # Fetch the view and verify the query counts
-        with self.assertNumQueries(45):
+        with self.assertNumQueries(47):
             with check_mongo_calls(5):
                 url = course_home_url(self.course)
                 self.client.get(url)
diff --git a/openedx/features/course_experience/tests/views/test_course_sock.py b/openedx/features/course_experience/tests/views/test_course_sock.py
new file mode 100644
index 0000000000000000000000000000000000000000..6da4e05fb26e1a6bd8573898f240c84f226419f6
--- /dev/null
+++ b/openedx/features/course_experience/tests/views/test_course_sock.py
@@ -0,0 +1,115 @@
+"""
+Tests for course verification sock
+"""
+
+import datetime
+import ddt
+
+from course_modes.models import CourseMode
+from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag
+from openedx.features.course_experience import DISPLAY_COURSE_SOCK
+from student.tests.factories import UserFactory, CourseEnrollmentFactory
+from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
+from xmodule.modulestore.tests.factories import CourseFactory
+from .test_course_home import course_home_url
+
+TEST_PASSWORD = 'test'
+TEST_VERIFICATION_SOCK_LOCATOR = '<div class="verification-sock">'
+TEST_COURSE_PRICE = 50
+
+
+@ddt.ddt
+class TestCourseSockView(SharedModuleStoreTestCase):
+    """
+    Tests for the course verification sock fragment view.
+    """
+    @classmethod
+    def setUpClass(cls):
+        super(TestCourseSockView, cls).setUpClass()
+
+        # Create four courses
+        cls.standard_course = CourseFactory.create()
+        cls.verified_course = CourseFactory.create()
+        cls.verified_course_update_expired = CourseFactory.create()
+        cls.verified_course_already_enrolled = CourseFactory.create()
+
+        # Assign each verifiable course a upgrade deadline
+        cls._add_course_mode(cls.verified_course, upgrade_deadline_expired=False)
+        cls._add_course_mode(cls.verified_course_update_expired, upgrade_deadline_expired=True)
+        cls._add_course_mode(cls.verified_course_already_enrolled, upgrade_deadline_expired=False)
+
+    def setUp(self):
+        super(TestCourseSockView, self).setUp()
+        self.user = UserFactory.create()
+
+        # Enroll the user in the four courses
+        CourseEnrollmentFactory.create(user=self.user, course_id=self.standard_course.id)
+        CourseEnrollmentFactory.create(user=self.user, course_id=self.verified_course.id)
+        CourseEnrollmentFactory.create(user=self.user, course_id=self.verified_course_update_expired.id)
+        CourseEnrollmentFactory.create(user=self.user, course_id=self.verified_course_already_enrolled.id, mode=CourseMode.VERIFIED)
+
+        # Log the user in
+        self.client.login(username=self.user.username, password=TEST_PASSWORD)
+
+    @override_waffle_flag(DISPLAY_COURSE_SOCK, active=True)
+    def test_standard_course(self):
+        """
+        Assure that a course that cannot be verified does
+        not have a visible verification sock.
+        """
+        response = self.client.get(course_home_url(self.standard_course))
+        self.assertEqual(self.is_verified_sock_visible(response), False,
+                         'Student should not be able to see sock in a unverifiable course.')
+
+    @override_waffle_flag(DISPLAY_COURSE_SOCK, active=True)
+    def test_verified_course(self):
+        """
+        Assure that a course that can be verified has a
+        visible verification sock.
+        """
+        response = self.client.get(course_home_url(self.verified_course))
+        self.assertEqual(self.is_verified_sock_visible(response), True,
+                         'Student should be able to see sock in a verifiable course.')
+
+    @override_waffle_flag(DISPLAY_COURSE_SOCK, active=True)
+    def test_verified_course_updated_expired(self):
+        """
+        Assure that a course that has an expired upgrade
+        date does not display the verification sock.
+        """
+        response = self.client.get(course_home_url(self.verified_course_update_expired))
+        self.assertEqual(self.is_verified_sock_visible(response), False,
+                         'Student should be able to see sock in a verifiable course if the update expiration date has passed.')
+
+    @override_waffle_flag(DISPLAY_COURSE_SOCK, active=True)
+    def test_verified_course_user_already_upgraded(self):
+        """
+        Assure that a user that has already upgraded to a
+        verified status cannot see the verification sock.
+        """
+        response = self.client.get(course_home_url(self.verified_course_already_enrolled))
+        self.assertEqual(self.is_verified_sock_visible(response), False,
+                         'Student should be able to see sock if they have already upgraded to verified mode.')
+
+    @classmethod
+    def is_verified_sock_visible(cls, response):
+        return TEST_VERIFICATION_SOCK_LOCATOR in response.content
+
+    @classmethod
+    def _add_course_mode(cls, course, upgrade_deadline_expired=False):
+        """
+        Adds a course mode to the test course.
+        """
+        upgrade_exp_date = datetime.datetime.now()
+        if upgrade_deadline_expired:
+            upgrade_exp_date = upgrade_exp_date - datetime.timedelta(days=21)
+        else:
+            upgrade_exp_date = upgrade_exp_date + datetime.timedelta(days=21)
+
+        CourseMode(
+            course_id=course.id,
+            mode_slug=CourseMode.VERIFIED,
+            mode_display_name="Verified Certificate",
+            min_price=TEST_COURSE_PRICE,
+            _expiration_datetime=upgrade_exp_date,  # pylint: disable=protected-access
+        ).save()
diff --git a/openedx/features/course_experience/urls.py b/openedx/features/course_experience/urls.py
index 42372fb9f832c8398bf454b253a08fe09aa8d615..39d5ecf83354196d338bcdcaa9383eade3b34a16 100644
--- a/openedx/features/course_experience/urls.py
+++ b/openedx/features/course_experience/urls.py
@@ -8,6 +8,7 @@ from views.course_home import CourseHomeFragmentView, CourseHomeView
 from views.course_outline import CourseOutlineFragmentView
 from views.course_updates import CourseUpdatesFragmentView, CourseUpdatesView
 from views.welcome_message import WelcomeMessageFragmentView
+from views.course_sock import CourseSockFragmentView
 
 urlpatterns = [
     url(
@@ -40,4 +41,9 @@ urlpatterns = [
         WelcomeMessageFragmentView.as_view(),
         name='openedx.course_experience.welcome_message_fragment_view',
     ),
+    url(
+        r'course_sock_fragment$',
+        CourseSockFragmentView.as_view(),
+        name='openedx.course_experience.course_sock_fragment_view',
+    ),
 ]
diff --git a/openedx/features/course_experience/views/course_home.py b/openedx/features/course_experience/views/course_home.py
index aa3922fc264769f969cdfbff264ae97018d456e4..aa6a43fbf6e359ef8cf1c852d1e4b4b5617c7477 100644
--- a/openedx/features/course_experience/views/course_home.py
+++ b/openedx/features/course_experience/views/course_home.py
@@ -20,6 +20,7 @@ from ..utils import get_course_outline_block_tree
 from .course_dates import CourseDatesFragmentView
 from .course_outline import CourseOutlineFragmentView
 from .welcome_message import WelcomeMessageFragmentView
+from .course_sock import CourseSockFragmentView
 
 
 class CourseHomeView(CourseTabView):
@@ -105,6 +106,9 @@ class CourseHomeFragmentView(EdxFragmentView):
         # TODO: Use get_course_overview_with_access and blocks api
         course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True)
 
+        # Render the verification sock as a fragment
+        course_sock_fragment = CourseSockFragmentView().render_to_fragment(request, course=course, **kwargs)
+
         # Get the handouts
         handouts_html = get_course_info_section(request, request.user, course, 'handouts')
 
@@ -119,6 +123,7 @@ class CourseHomeFragmentView(EdxFragmentView):
             'resume_course_url': resume_course_url,
             'dates_fragment': dates_fragment,
             'welcome_message_fragment': welcome_message_fragment,
+            'course_sock_fragment': course_sock_fragment,
             'disable_courseware_js': True,
             'uses_pattern_library': True,
         }
diff --git a/openedx/features/course_experience/views/course_sock.py b/openedx/features/course_experience/views/course_sock.py
new file mode 100644
index 0000000000000000000000000000000000000000..57863ed3a354613cfb35e2888f62e289db53850c
--- /dev/null
+++ b/openedx/features/course_experience/views/course_sock.py
@@ -0,0 +1,56 @@
+"""
+Fragment for rendering the course's sock and associated toggle button.
+"""
+from datetime import datetime
+
+from django.conf import settings
+from django.template.loader import render_to_string
+from opaque_keys.edx.keys import CourseKey
+from web_fragments.fragment import Fragment
+
+from student.models import CourseEnrollment
+from course_modes.models import CourseMode
+from courseware.date_summary import VerifiedUpgradeDeadlineDate
+from courseware.courses import get_course_with_access
+from courseware.views.views import get_course_prices
+from openedx.core.djangoapps.plugin_api.views import EdxFragmentView
+
+
+class CourseSockFragmentView(EdxFragmentView):
+    """
+    A fragment to provide extra functionality in a dropdown sock.
+    """
+    def render_to_fragment(self, request, course, **kwargs):
+        """
+        Render the course's sock fragment.
+        """
+        context = self.get_verification_context(request, course)
+        html = render_to_string('course_experience/course-sock-fragment.html', context)
+        return Fragment(html)
+
+    def get_verification_context(self, request, course):
+        course_key = CourseKey.from_string(unicode(course.id))
+
+        # Establish whether the course has a verified mode
+        available_modes = CourseMode.modes_for_course_dict(unicode(course.id))
+        has_verified_mode = CourseMode.has_verified_mode(available_modes)
+
+        # Establish whether the user is already enrolled
+        is_already_verified = CourseEnrollment.is_enrolled_as_verified(request.user.id, course_key)
+
+        # Establish whether the verification deadline has already passed
+        verification_deadline = VerifiedUpgradeDeadlineDate(course, request.user)
+        deadline_has_passed = verification_deadline.deadline_has_passed()
+
+        show_course_sock = has_verified_mode and not is_already_verified and not deadline_has_passed
+
+        # Get the price of the course and format correctly
+        course_prices = get_course_prices(course)
+
+        context = {
+            'show_course_sock': show_course_sock,
+            'course_price': course_prices[1],
+            'course_id': course.id
+        }
+
+        return context
diff --git a/webpack.config.js b/webpack.config.js
index 5a5800a3f2fba97cd543589834d510e598f03316..6719071a23cafd6617b50725ac9a6ce290dd406c 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -19,6 +19,7 @@ var wpconfig = {
 
     entry: {
         CourseOutline: './openedx/features/course_experience/static/course_experience/js/CourseOutline.js',
+        CourseSock: './openedx/features/course_experience/static/course_experience/js/CourseSock.js',
         Import: './cms/static/js/features/import/factories/import.js'
     },