diff --git a/common/djangoapps/student/helpers.py b/common/djangoapps/student/helpers.py
index fa925a118077f698698aa21610067e02dcb2eafc..9e49ce19dc9c3e986b28911bbd9c929e24cda74e 100644
--- a/common/djangoapps/student/helpers.py
+++ b/common/djangoapps/student/helpers.py
@@ -33,7 +33,6 @@ from lms.djangoapps.verify_student.services import IDVerificationService
 from lms.djangoapps.verify_student.utils import is_verification_expiring_soon, verification_for_datetime
 from openedx.core.djangoapps.certificates.api import certificates_viewable_for_course
 from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
-from openedx.core.djangoapps.theming import helpers as theming_helpers
 from openedx.core.djangoapps.theming.helpers import get_themes
 from openedx.core.djangoapps.user_authn.utils import is_safe_login_or_logout_redirect
 from student.models import (
@@ -458,19 +457,12 @@ def cert_info(user, course_overview):
         course_overview (CourseOverview): A course.
 
     Returns:
-        dict: A dictionary with keys:
-            'status': one of 'generating', 'downloadable', 'notpassing', 'processing', 'restricted', 'unavailable', or
-                'certificate_earned_but_not_available'
-            'download_url': url, only present if show_download_url is True
-            'show_survey_button': bool
-            'survey_url': url, only if show_survey_button is True
-            'grade': if status is not 'processing'
-            'can_unenroll': if status allows for unenrollment
+        See _cert_info
     """
     return _cert_info(
         user,
         course_overview,
-        certificate_status_for_student(user, course_overview.id)
+        certificate_status_for_student(user, course_overview.id),
     )
 
 
@@ -481,6 +473,23 @@ def _cert_info(user, course_overview, cert_status):
     Arguments:
         user (User): A user.
         course_overview (CourseOverview): A course.
+        cert_status (dict): dictionary containing information about certificate status for the user
+
+    Returns:
+        dictionary containing:
+            'status': one of 'generating', 'downloadable', 'notpassing', 'restricted', 'auditing',
+                'processing', 'unverified', 'unavailable', or 'certificate_earned_but_not_available'
+            'show_survey_button': bool
+            'can_unenroll': if status allows for unenrollment
+
+        The dictionary may also contain:
+            'linked_in_url': url to add cert to LinkedIn profile
+            'survey_url': url, only if course_overview.end_of_course_survey_url is not None
+            'show_cert_web_view': bool if html web certs are enabled and there is an active web cert
+            'cert_web_view_url': url if html web certs are enabled and there is an active web cert
+            'download_url': url to download a cert
+            'grade': if status is in 'generating', 'downloadable', 'notpassing', 'restricted',
+                'auditing', or 'unverified'
     """
     # simplify the status for the template using this lookup table
     template_state = {
@@ -507,7 +516,7 @@ def _cert_info(user, course_overview, cert_status):
         return default_info
 
     status = template_state.get(cert_status['status'], default_status)
-    is_hidden_status = status in ('unavailable', 'processing', 'generating', 'notpassing', 'auditing')
+    is_hidden_status = status in ('processing', 'generating', 'notpassing', 'auditing')
 
     if (
         not certificates_viewable_for_course(course_overview) and
@@ -563,15 +572,9 @@ def _cert_info(user, course_overview, cert_status):
             # Clicking this button sends the user to LinkedIn where they
             # can add the certificate information to their profile.
             linkedin_config = LinkedInAddToProfileConfiguration.current()
-
-            # posting certificates to LinkedIn is not currently
-            # supported in White Labels
-            if linkedin_config.enabled and not theming_helpers.is_request_in_themed_site():
+            if linkedin_config.is_enabled():
                 status_dict['linked_in_url'] = linkedin_config.add_to_profile_url(
-                    course_overview.id,
-                    course_overview.display_name,
-                    cert_status.get('mode'),
-                    cert_status['download_url']
+                    course_overview.display_name, cert_status.get('mode'), cert_status['download_url'],
                 )
 
     if status in {'generating', 'downloadable', 'notpassing', 'restricted', 'auditing', 'unverified'}:
diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py
index b55d0afa61379e5ec95c6ed46b2f52370d9e9a03..7b7f5e74fae58b99e81b99c22cb7bb119d4b0e85 100644
--- a/common/djangoapps/student/models.py
+++ b/common/djangoapps/student/models.py
@@ -16,10 +16,11 @@ import hashlib
 import json
 import logging
 import uuid
-from collections import OrderedDict, defaultdict, namedtuple
+from collections import defaultdict, namedtuple
 from datetime import datetime, timedelta
 from functools import total_ordering
 from importlib import import_module
+from urllib.parse import urlencode
 
 import six
 from config_models.models import ConfigurationModel
@@ -51,7 +52,6 @@ from pytz import UTC
 from simple_history.models import HistoricalRecords
 from six import text_type
 from six.moves import range
-from six.moves.urllib.parse import urlencode
 from slumber.exceptions import HttpClientError, HttpServerError
 from user_util import user_util
 
@@ -2527,23 +2527,21 @@ class LinkedInAddToProfileConfiguration(ConfigurationModel):
     """
     LinkedIn Add to Profile Configuration
 
-    This configuration enables the "Add to Profile" LinkedIn
-    button on the student dashboard.  The button appears when
-    users have a certificate available; when clicked,
-    users are sent to the LinkedIn site with a pre-filled
-    form allowing them to add the certificate to their
-    LinkedIn profile.
+    This configuration enables the 'Add to Profile' LinkedIn button. The button
+    appears when users have a certificate available; when clicked, users are sent
+    to the LinkedIn site with a pre-filled form allowing them to add the
+    certificate to their LinkedIn profile.
+
+    See https://addtoprofile.linkedin.com/ for documentation on parameters
 
     .. no_pii:
     """
 
     MODE_TO_CERT_NAME = {
-        "honor": _(u"{platform_name} Honor Code Certificate for {course_name}"),
-        "verified": _(u"{platform_name} Verified Certificate for {course_name}"),
-        "professional": _(u"{platform_name} Professional Certificate for {course_name}"),
-        "no-id-professional": _(
-            u"{platform_name} Professional Certificate for {course_name}"
-        ),
+        'honor': _('{platform_name} Honor Code Certificate for {course_name}'),
+        'verified': _('{platform_name} Verified Certificate for {course_name}'),
+        'professional': _('{platform_name} Professional Certificate for {course_name}'),
+        'no-id-professional': _('{platform_name} Professional Certificate for {course_name}'),
     }
 
     company_identifier = models.TextField(
@@ -2567,33 +2565,43 @@ class LinkedInAddToProfileConfiguration(ConfigurationModel):
         )
     )
 
-    def add_to_profile_url(self, course_key, course_name, cert_mode, cert_url, source="o", target="dashboard"):
-        """Construct the URL for the "add to profile" button.
+    def is_enabled(self, *key_fields):
+        """
+        Checks both the model itself and share_settings to see if LinkedIn Add to Profile is enabled
+        """
+        enabled = super().is_enabled(*key_fields)
+        share_settings = configuration_helpers.get_value('SOCIAL_SHARING_SETTINGS', settings.SOCIAL_SHARING_SETTINGS)
+        return share_settings.get('CERTIFICATE_LINKEDIN', enabled)
+
+    def add_to_profile_url(self, course_name, cert_mode, cert_url, certificate=None):
+        """
+        Construct the URL for the "add to profile" button. This will autofill the form based on
+        the params provided.
 
         Arguments:
-            course_key (CourseKey): The identifier for the course.
-            course_name (unicode): The display name of the course.
+            course_name (str): The display name of the course.
             cert_mode (str): The course mode of the user's certificate (e.g. "verified", "honor", "professional")
-            cert_url (str): The download URL for the certificate.
+            cert_url (str): The URL for the certificate.
 
         Keyword Arguments:
-            source (str): Either "o" (for onsite/UI), "e" (for emails), or "m" (for mobile)
-            target (str): An identifier for the occurrance of the button.
-
+            certificate (GeneratedCertificate): a GeneratedCertificate object for the user and course.
+                If provided, this function will also autofill the certId and issue date for the cert.
         """
-        company_identifier = configuration_helpers.get_value('LINKEDIN_COMPANY_ID', self.company_identifier)
-        params = OrderedDict([
-            ('_ed', company_identifier),
-            ('pfCertificationName', self._cert_name(course_name, cert_mode).encode('utf-8')),
-            ('pfCertificationUrl', cert_url),
-            ('source', source)
-        ])
+        params = {
+            'name': self._cert_name(course_name, cert_mode),
+            'certUrl': cert_url,
+        }
 
-        tracking_code = self._tracking_code(course_key, cert_mode, target)
-        if tracking_code is not None:
-            params['trk'] = tracking_code
+        params.update(self._organization_information())
 
-        return u'http://www.linkedin.com/profile/add?{params}'.format(
+        if certificate:
+            params.update({
+                'certId': certificate.verify_uuid,
+                'issueYear': certificate.created_date.year,
+                'issueMonth': certificate.created_date.month,
+            })
+
+        return 'https://www.linkedin.com/profile/add?startTask=CERTIFICATION_NAME&{params}'.format(
             params=urlencode(params)
         )
 
@@ -2608,10 +2616,7 @@ class LinkedInAddToProfileConfiguration(ConfigurationModel):
         Returns:
             str: The formatted string to display for the name field on the LinkedIn Add to Profile dialog.
         """
-        default_cert_name = self.MODE_TO_CERT_NAME.get(
-            cert_mode,
-            _(u"{platform_name} Certificate for {course_name}")
-        )
+        default_cert_name = self.MODE_TO_CERT_NAME.get(cert_mode, _('{platform_name} Certificate for {course_name}'))
         # Look for an override of the certificate name in the SOCIAL_SHARING_SETTINGS setting
         share_settings = configuration_helpers.get_value('SOCIAL_SHARING_SETTINGS', settings.SOCIAL_SHARING_SETTINGS)
         cert_name = share_settings.get('CERTIFICATE_LINKEDIN_MODE_TO_CERT_NAME', {}).get(cert_mode, default_cert_name)
@@ -2621,41 +2626,19 @@ class LinkedInAddToProfileConfiguration(ConfigurationModel):
             course_name=course_name
         )
 
-    def _tracking_code(self, course_key, cert_mode, target):
-        """Create a tracking code for the button.
-
-        Tracking codes are used by LinkedIn to collect
-        analytics about certifications users are adding
-        to their profiles.
-
-        The tracking code format is:
-            &trk=[partner name]-[certificate type]-[date]-[target field]
-
-        In our case, we're sending:
-            &trk=edx-{COURSE ID}_{COURSE MODE}-{TARGET}
-
-        If no partner code is configured, then this will
-        return None, indicating that tracking codes are disabled.
-
-        Arguments:
-
-            course_key (CourseKey): The identifier for the course.
-            cert_mode (str): The enrollment mode for the course.
-            target (str): Identifier for where the button is located.
+    def _organization_information(self):
+        """
+        Returns organization information for use in the URL parameters for add to profile.
 
         Returns:
-            unicode or None
-
-        """
-        return (
-            u"{partner}-{course_key}_{cert_mode}-{target}".format(
-                partner=self.trk_partner_name,
-                course_key=text_type(course_key),
-                cert_mode=cert_mode,
-                target=target
-            )
-            if self.trk_partner_name else None
-        )
+            dict: Either the organization ID on LinkedIn or the organization's name
+                Will be used to prefill the organization on the add to profile action.
+        """
+        org_id = configuration_helpers.get_value('LINKEDIN_COMPANY_ID', self.company_identifier)
+        # Prefer organization ID per documentation at https://addtoprofile.linkedin.com/
+        if org_id:
+            return {'organizationId': org_id}
+        return {'organizationName': configuration_helpers.get_value('platform_name', settings.PLATFORM_NAME)}
 
 
 @python_2_unicode_compatible
diff --git a/common/djangoapps/student/tests/test_certificates.py b/common/djangoapps/student/tests/test_certificates.py
index f7d5c1d5b739a1ba340cffa8800790c9697a4952..5efa5962bca0120f615f0ae47a7ed1ab1cd07790 100644
--- a/common/djangoapps/student/tests/test_certificates.py
+++ b/common/djangoapps/student/tests/test_certificates.py
@@ -5,7 +5,6 @@ import datetime
 import unittest
 
 import ddt
-import mock
 from django.conf import settings
 from django.test.utils import override_settings
 from django.urls import reverse
@@ -15,8 +14,9 @@ from pytz import UTC
 from course_modes.models import CourseMode
 from lms.djangoapps.certificates.api import get_certificate_url
 from lms.djangoapps.certificates.models import CertificateStatuses
-from lms.djangoapps.certificates.tests.factories import GeneratedCertificateFactory
-from student.models import LinkedInAddToProfileConfiguration
+from lms.djangoapps.certificates.tests.factories import (
+    GeneratedCertificateFactory, LinkedInAddToProfileConfigurationFactory
+)
 from student.tests.factories import CourseEnrollmentFactory, UserFactory
 from xmodule.modulestore import ModuleStoreEnum
 from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
@@ -191,10 +191,12 @@ class CertificateDisplayTest(CertificateDisplayTestBase):
             u'do not have a current verified identity with {platform_name}'
             .format(platform_name=settings.PLATFORM_NAME))
 
-    def test_post_to_linkedin_invisibility(self):
+    def test_post_to_linkedin_visibility(self):
         """
         Verifies that the post certificate to linked button
         does not appear by default (when config is not set)
+        Then Verifies that the post certificate to linked button appears
+        as expected once a config is set
         """
         self._create_certificate('honor')
 
@@ -202,39 +204,10 @@ class CertificateDisplayTest(CertificateDisplayTestBase):
         # button should not be visible
         self._check_linkedin_visibility(False)
 
-    def test_post_to_linkedin_visibility(self):
-        """
-        Verifies that the post certificate to linked button appears
-        as expected
-        """
-        self._create_certificate('honor')
-
-        config = LinkedInAddToProfileConfiguration(
-            company_identifier='0_mC_o2MizqdtZEmkVXjH4eYwMj4DnkCWrZP_D9',
-            enabled=True
-        )
-        config.save()
-
+        LinkedInAddToProfileConfigurationFactory()
         # now we should see it
         self._check_linkedin_visibility(True)
 
-    @mock.patch("openedx.core.djangoapps.theming.helpers.is_request_in_themed_site", mock.Mock(return_value=True))
-    def test_post_to_linkedin_site_specific(self):
-        """
-        Verifies behavior for themed sites which disables the post to LinkedIn
-        feature (for now)
-        """
-        self._create_certificate('honor')
-
-        config = LinkedInAddToProfileConfiguration(
-            company_identifier='0_mC_o2MizqdtZEmkVXjH4eYwMj4DnkCWrZP_D9',
-            enabled=True
-        )
-        config.save()
-
-        # now we should not see it because we are in a themed site
-        self._check_linkedin_visibility(False)
-
 
 @ddt.ddt
 @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
diff --git a/common/djangoapps/student/tests/test_linkedin.py b/common/djangoapps/student/tests/test_linkedin.py
index a237ead911853fdd1354b7755b5d582e14b9dadb..b7eee9a4198785ffaae613eb8d3d196e6e711119 100644
--- a/common/djangoapps/student/tests/test_linkedin.py
+++ b/common/djangoapps/student/tests/test_linkedin.py
@@ -2,120 +2,101 @@
 """Tests for LinkedIn Add to Profile configuration. """
 
 
+from urllib.parse import quote
 import ddt
+
 from django.conf import settings
 from django.test import TestCase
-from opaque_keys.edx.locator import CourseLocator
-from six.moves.urllib.parse import quote, urlencode
 
+from lms.djangoapps.certificates.tests.factories import LinkedInAddToProfileConfigurationFactory
 from openedx.core.djangoapps.site_configuration.tests.test_util import with_site_configuration_context
-from student.models import LinkedInAddToProfileConfiguration
 
 
 @ddt.ddt
 class LinkedInAddToProfileUrlTests(TestCase):
     """Tests for URL generation of LinkedInAddToProfileConfig. """
 
-    COURSE_KEY = CourseLocator(org="edx", course="DemoX", run="Demo_Course")
-    COURSE_NAME = u"Test Course ☃"
-    CERT_URL = u"http://s3.edx/cert"
+    COURSE_NAME = 'Test Course ☃'
+    CERT_URL = 'http://s3.edx/cert'
     SITE_CONFIGURATION = {
         'SOCIAL_SHARING_SETTINGS': {
             'CERTIFICATE_LINKEDIN_MODE_TO_CERT_NAME': {
-                'honor': u'{platform_name} Honor Code Credential for {course_name}',
-                'verified': u'{platform_name} Verified Credential for {course_name}',
-                'professional': u'{platform_name} Professional Credential for {course_name}',
-                'no-id-professional': u'{platform_name} Professional Credential for {course_name}',
+                'honor': '{platform_name} Honor Code Credential for {course_name}',
+                'verified': '{platform_name} Verified Credential for {course_name}',
+                'professional': '{platform_name} Professional Credential for {course_name}',
+                'no-id-professional': '{platform_name} Professional Credential for {course_name}',
             }
         }
     }
 
     @ddt.data(
-        ('honor', u'Honor+Code+Certificate+for+Test+Course+%E2%98%83'),
-        ('verified', u'Verified+Certificate+for+Test+Course+%E2%98%83'),
-        ('professional', u'Professional+Certificate+for+Test+Course+%E2%98%83'),
-        ('default_mode', u'Certificate+for+Test+Course+%E2%98%83')
+        ('honor', 'Honor+Code+Certificate+for+Test+Course+%E2%98%83'),
+        ('verified', 'Verified+Certificate+for+Test+Course+%E2%98%83'),
+        ('professional', 'Professional+Certificate+for+Test+Course+%E2%98%83'),
+        ('default_mode', 'Certificate+for+Test+Course+%E2%98%83')
     )
     @ddt.unpack
     def test_linked_in_url(self, cert_mode, expected_cert_name):
-        config = LinkedInAddToProfileConfiguration(
-            company_identifier='0_mC_o2MizqdtZEmkVXjH4eYwMj4DnkCWrZP_D9',
-            enabled=True
-        )
-
-        expected_url = (
-            'http://www.linkedin.com/profile/add'
-            '?_ed=0_mC_o2MizqdtZEmkVXjH4eYwMj4DnkCWrZP_D9&'
-            'pfCertificationName={platform_name}+{expected_cert_name}&'
-            'pfCertificationUrl=http%3A%2F%2Fs3.edx%2Fcert&'
-            'source=o'
-        ).format(
-            expected_cert_name=expected_cert_name,
-            platform_name=quote(settings.PLATFORM_NAME.encode('utf-8'))
-        )
-
-        actual_url = config.add_to_profile_url(
-            self.COURSE_KEY,
-            self.COURSE_NAME,
-            cert_mode,
-            self.CERT_URL
-        )
-
-        self.assertEqual(actual_url, expected_url)
+        config = LinkedInAddToProfileConfigurationFactory()
+
+        # We can switch to this once edx-platform reaches Python 3.8
+        # expected_url = (
+        #     'https://www.linkedin.com/profile/add?startTask=CERTIFICATION_NAME&'
+        #     'name={platform}+{cert_name}&certUrl={cert_url}&'
+        #     'organizationId={company_identifier}'
+        # ).format(
+        #     platform=quote(settings.PLATFORM_NAME.encode('utf-8')),
+        #     cert_name=expected_cert_name,
+        #     cert_url=quote(self.CERT_URL, safe=''),
+        #     company_identifier=config.company_identifier,
+        # )
+
+        actual_url = config.add_to_profile_url(self.COURSE_NAME, cert_mode, self.CERT_URL)
+
+        # We can switch to this instead of the assertIn once edx-platform reaches Python 3.8
+        # There was a problem with dict ordering in the add_to_profile_url function that will go away then.
+        # self.assertEqual(actual_url, expected_url)
+
+        self.assertIn('https://www.linkedin.com/profile/add?startTask=CERTIFICATION_NAME', actual_url)
+        self.assertIn('&name={platform}+{cert_name}'.format(
+            platform=quote(settings.PLATFORM_NAME.encode('utf-8')), cert_name=expected_cert_name
+        ), actual_url)
+        self.assertIn('&certUrl={cert_url}'.format(cert_url=quote(self.CERT_URL, safe='')), actual_url)
+        self.assertIn('&organizationId={org_id}'.format(org_id=config.company_identifier), actual_url)
 
     @ddt.data(
-        ('honor', u'Honor+Code+Credential+for+Test+Course+%E2%98%83'),
-        ('verified', u'Verified+Credential+for+Test+Course+%E2%98%83'),
-        ('professional', u'Professional+Credential+for+Test+Course+%E2%98%83'),
-        ('no-id-professional', u'Professional+Credential+for+Test+Course+%E2%98%83'),
-        ('default_mode', u'Certificate+for+Test+Course+%E2%98%83')
+        ('honor', 'Honor+Code+Credential+for+Test+Course+%E2%98%83'),
+        ('verified', 'Verified+Credential+for+Test+Course+%E2%98%83'),
+        ('professional', 'Professional+Credential+for+Test+Course+%E2%98%83'),
+        ('no-id-professional', 'Professional+Credential+for+Test+Course+%E2%98%83'),
+        ('default_mode', 'Certificate+for+Test+Course+%E2%98%83')
     )
     @ddt.unpack
     def test_linked_in_url_with_cert_name_override(self, cert_mode, expected_cert_name):
-        config = LinkedInAddToProfileConfiguration(
-            company_identifier='0_mC_o2MizqdtZEmkVXjH4eYwMj4DnkCWrZP_D9',
-            enabled=True
-        )
-
-        expected_url = (
-            'http://www.linkedin.com/profile/add'
-            '?_ed=0_mC_o2MizqdtZEmkVXjH4eYwMj4DnkCWrZP_D9&'
-            'pfCertificationName={platform_name}+{expected_cert_name}&'
-            'pfCertificationUrl=http%3A%2F%2Fs3.edx%2Fcert&'
-            'source=o'
-        ).format(
-            expected_cert_name=expected_cert_name,
-            platform_name=quote(settings.PLATFORM_NAME.encode('utf-8'))
-        )
+        config = LinkedInAddToProfileConfigurationFactory()
+
+        # We can switch to this once edx-platform reaches Python 3.8
+        # expected_url = (
+        #     'https://www.linkedin.com/profile/add?startTask=CERTIFICATION_NAME&'
+        #     'name={platform}+{cert_name}&certUrl={cert_url}&'
+        #     'organizationId={company_identifier}'
+        # ).format(
+        #     platform=quote(settings.PLATFORM_NAME.encode('utf-8')),
+        #     cert_name=expected_cert_name,
+        #     cert_url=quote(self.CERT_URL, safe=''),
+        #     company_identifier=config.company_identifier,
+        # )
 
         with with_site_configuration_context(configuration=self.SITE_CONFIGURATION):
-            actual_url = config.add_to_profile_url(
-                self.COURSE_KEY,
-                self.COURSE_NAME,
-                cert_mode,
-                self.CERT_URL
-            )
-
-            self.assertEqual(actual_url, expected_url)
-
-    def test_linked_in_url_tracking_code(self):
-        config = LinkedInAddToProfileConfiguration(
-            company_identifier="abcd123",
-            trk_partner_name="edx",
-            enabled=True
-        )
-
-        expected_param = urlencode({
-            'trk': u'edx-{course_key}_honor-dashboard'.format(
-                course_key=self.COURSE_KEY
-            )
-        })
-
-        actual_url = config.add_to_profile_url(
-            self.COURSE_KEY,
-            self.COURSE_NAME,
-            'honor',
-            self.CERT_URL
-        )
-
-        self.assertIn(expected_param, actual_url)
+            actual_url = config.add_to_profile_url(self.COURSE_NAME, cert_mode, self.CERT_URL)
+
+            # We can switch to this instead of the assertIn once edx-platform reaches Python 3.8
+            # There was a problem with dict ordering in the add_to_profile_url function that will go away then.
+            # self.assertEqual(actual_url, expected_url)
+
+            self.assertIn('https://www.linkedin.com/profile/add?startTask=CERTIFICATION_NAME', actual_url)
+            self.assertIn('&name={platform}+{cert_name}'.format(
+                platform=quote(settings.PLATFORM_NAME.encode('utf-8')), cert_name=expected_cert_name
+            ), actual_url)
+            self.assertIn('&certUrl={cert_url}'.format(cert_url=quote(self.CERT_URL, safe='')), actual_url)
+            self.assertIn('&organizationId={org_id}'.format(org_id=config.company_identifier), actual_url)
diff --git a/common/djangoapps/student/tests/tests.py b/common/djangoapps/student/tests/tests.py
index 1fc4c6c45adc04b2426e0c798e5bd7afe69bf74e..d7017d3bbafb008c6df27b6a150d89a7198358ac 100644
--- a/common/djangoapps/student/tests/tests.py
+++ b/common/djangoapps/student/tests/tests.py
@@ -7,10 +7,10 @@ Miscellaneous tests for the student app.
 import logging
 import unittest
 from datetime import datetime, timedelta
+from urllib.parse import quote
 
 import ddt
 import pytz
-import six
 from config_models.models import cache
 from django.conf import settings
 from django.contrib.auth.models import AnonymousUser, User
@@ -22,11 +22,7 @@ from mock import Mock, patch
 from opaque_keys.edx.keys import CourseKey
 from opaque_keys.edx.locations import CourseLocator
 from pyquery import PyQuery as pq
-from six import text_type
-from six.moves import range
-from six.moves.urllib.parse import quote
 
-from bulk_email.models import Optout
 from course_modes.models import CourseMode
 from course_modes.tests.factories import CourseModeFactory
 from lms.djangoapps.certificates.models import CertificateStatuses
@@ -34,6 +30,7 @@ from lms.djangoapps.certificates.tests.factories import GeneratedCertificateFact
 from lms.djangoapps.verify_student.tests import TestVerificationBase
 from openedx.core.djangoapps.catalog.tests.factories import CourseFactory as CatalogCourseFactory
 from openedx.core.djangoapps.catalog.tests.factories import CourseRunFactory, ProgramFactory, generate_course_run_key
+from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
 from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin
 from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin
 from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_unless_lms
@@ -58,7 +55,7 @@ log = logging.getLogger(__name__)
 
 @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
 @ddt.ddt
-class CourseEndingTest(TestCase):
+class CourseEndingTest(ModuleStoreTestCase):
     """Test things related to course endings: certificates, surveys, etc"""
 
     def test_process_survey_link(self):
@@ -74,12 +71,19 @@ class CourseEndingTest(TestCase):
 
     @patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': False})
     def test_cert_info(self):
-        user = Mock(username="fred", id="1")
+        user = UserFactory.create()
         survey_url = "http://a_survey.com"
-        course = Mock(
+        course = CourseOverviewFactory.create(
             end_of_course_survey_url=survey_url,
             certificates_display_behavior='end',
-            id=CourseLocator(org="x", course="y", run="z"),
+        )
+        cert = GeneratedCertificateFactory.create(
+            user=user,
+            course_id=course.id,
+            status=CertificateStatuses.downloadable,
+            mode='honor',
+            grade='67',
+            download_url='http://s3.edx/cert'
         )
 
         self.assertEqual(
@@ -91,19 +95,19 @@ class CourseEndingTest(TestCase):
             }
         )
 
-        cert_status = {'status': 'unavailable'}
+        cert_status = {'status': 'unavailable', 'mode': 'honor', 'uuid': None}
         self.assertEqual(
             _cert_info(user, course, cert_status),
             {
                 'status': 'processing',
                 'show_survey_button': False,
-                'mode': None,
+                'mode': 'honor',
                 'linked_in_url': None,
                 'can_unenroll': True,
             }
         )
 
-        cert_status = {'status': 'generating', 'grade': '0.67', 'mode': 'honor'}
+        cert_status = {'status': 'generating', 'grade': '0.67', 'mode': 'honor', 'uuid': None}
         with patch('lms.djangoapps.grades.course_grade_factory.CourseGradeFactory.read') as patch_persisted_grade:
             patch_persisted_grade.return_value = Mock(percent=1.0)
             self.assertEqual(
@@ -119,7 +123,7 @@ class CourseEndingTest(TestCase):
                 }
             )
 
-        cert_status = {'status': 'generating', 'grade': '0.67', 'mode': 'honor'}
+        cert_status = {'status': 'generating', 'grade': '0.67', 'mode': 'honor', 'uuid': None}
         self.assertEqual(
             _cert_info(user, course, cert_status),
             {
@@ -133,19 +137,18 @@ class CourseEndingTest(TestCase):
             }
         )
 
-        download_url = 'http://s3.edx/cert'
         cert_status = {
             'status': 'downloadable',
             'grade': '0.67',
-            'download_url': download_url,
-            'mode': 'honor'
+            'download_url': cert.download_url,
+            'mode': 'honor',
+            'uuid': 'fakeuuidbutitsfine',
         }
-
         self.assertEqual(
             _cert_info(user, course, cert_status),
             {
                 'status': 'downloadable',
-                'download_url': download_url,
+                'download_url': cert.download_url,
                 'show_survey_button': True,
                 'survey_url': survey_url,
                 'grade': '0.67',
@@ -157,8 +160,9 @@ class CourseEndingTest(TestCase):
 
         cert_status = {
             'status': 'notpassing', 'grade': '0.67',
-            'download_url': download_url,
-            'mode': 'honor'
+            'download_url': cert.download_url,
+            'mode': 'honor',
+            'uuid': 'fakeuuidbutitsfine',
         }
         self.assertEqual(
             _cert_info(user, course, cert_status),
@@ -177,7 +181,7 @@ class CourseEndingTest(TestCase):
         course2 = Mock(end_of_course_survey_url=None, id=CourseLocator(org="a", course="b", run="c"))
         cert_status = {
             'status': 'notpassing', 'grade': '0.67',
-            'download_url': download_url, 'mode': 'honor'
+            'download_url': cert.download_url, 'mode': 'honor', 'uuid': 'fakeuuidbutitsfine'
         }
         self.assertEqual(
             _cert_info(user, course2, cert_status),
@@ -193,7 +197,7 @@ class CourseEndingTest(TestCase):
 
         # test when the display is unavailable or notpassing, we get the correct results out
         course2.certificates_display_behavior = 'early_no_info'
-        cert_status = {'status': 'unavailable'}
+        cert_status = {'status': 'unavailable', 'mode': 'honor', 'uuid': None}
         self.assertEqual(
             _cert_info(user, course2, cert_status),
             {
@@ -205,8 +209,9 @@ class CourseEndingTest(TestCase):
 
         cert_status = {
             'status': 'notpassing', 'grade': '0.67',
-            'download_url': download_url,
-            'mode': 'honor'
+            'download_url': cert.download_url,
+            'mode': 'honor',
+            'uuid': 'fakeuuidbutitsfine'
         }
         self.assertEqual(
             _cert_info(user, course2, cert_status),
@@ -234,18 +239,17 @@ class CourseEndingTest(TestCase):
         from the certs table is used on the learner dashboard.
         """
         expected_grade = max(filter(lambda x: x is not None, [persisted_grade, cert_grade]))
-        user = Mock(username="fred", id="1")
+        user = UserFactory.create()
         survey_url = "http://a_survey.com"
-        course = Mock(
+        course = CourseOverviewFactory.create(
             end_of_course_survey_url=survey_url,
             certificates_display_behavior='end',
-            id=CourseLocator(org="x", course="y", run="z"),
         )
 
         if cert_grade is not None:
-            cert_status = {'status': 'generating', 'grade': six.text_type(cert_grade), 'mode': 'honor'}
+            cert_status = {'status': 'generating', 'grade': str(cert_grade), 'mode': 'honor', 'uuid': None}
         else:
-            cert_status = {'status': 'generating', 'mode': 'honor'}
+            cert_status = {'status': 'generating', 'mode': 'honor', 'uuid': None}
 
         with patch('lms.djangoapps.grades.course_grade_factory.CourseGradeFactory.read') as patch_persisted_grade:
             patch_persisted_grade.return_value = Mock(percent=persisted_grade)
@@ -255,7 +259,7 @@ class CourseEndingTest(TestCase):
                     'status': 'generating',
                     'show_survey_button': True,
                     'survey_url': survey_url,
-                    'grade': six.text_type(expected_grade),
+                    'grade': str(expected_grade),
                     'mode': 'honor',
                     'linked_in_url': None,
                     'can_unenroll': False,
@@ -268,14 +272,13 @@ class CourseEndingTest(TestCase):
         when the learner has no persisted grade or grade
         in the certs table.
         """
-        user = Mock(username="fred", id="1")
+        user = UserFactory.create()
         survey_url = "http://a_survey.com"
-        course = Mock(
+        course = CourseOverviewFactory.create(
             end_of_course_survey_url=survey_url,
             certificates_display_behavior='end',
-            id=CourseLocator(org="x", course="y", run="z"),
         )
-        cert_status = {'status': 'generating', 'mode': 'honor'}
+        cert_status = {'status': 'generating', 'mode': 'honor', 'uuid': None}
 
         with patch('lms.djangoapps.grades.course_grade_factory.CourseGradeFactory.read') as patch_persisted_grade:
             patch_persisted_grade.return_value = None
@@ -422,7 +425,7 @@ class DashboardTest(ModuleStoreTestCase, TestVerificationBase):
         self.assertEqual(response.status_code, 200)
         self.assertNotContains(response, 'Add Certificate to LinkedIn')
 
-        response_url = 'http://www.linkedin.com/profile/add?_ed='
+        response_url = 'https://www.linkedin.com/profile/add?startTask=CERTIFICATION_NAME'
         self.assertNotContains(response, escape(response_url))
 
     @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@@ -432,49 +435,55 @@ class DashboardTest(ModuleStoreTestCase, TestVerificationBase):
         # should be visible. and it has URL value with valid parameters.
         self.client.login(username="jack", password="test")
 
-        LinkedInAddToProfileConfiguration.objects.create(
-            company_identifier='0_mC_o2MizqdtZEmkVXjH4eYwMj4DnkCWrZP_D9',
-            enabled=True
-        )
-
+        linkedin_config = LinkedInAddToProfileConfiguration.objects.create(company_identifier='1337', enabled=True)
         CourseModeFactory.create(
             course_id=self.course.id,
             mode_slug='verified',
             mode_display_name='verified',
             expiration_datetime=datetime.now(pytz.UTC) - timedelta(days=1)
         )
-
-        self.course.certificate_available_date = datetime.now(pytz.UTC) - timedelta(days=1)
         CourseEnrollment.enroll(self.user, self.course.id, mode='honor')
-
+        self.course.certificate_available_date = datetime.now(pytz.UTC) - timedelta(days=1)
         self.course.start = datetime.now(pytz.UTC) - timedelta(days=2)
         self.course.end = datetime.now(pytz.UTC) - timedelta(days=1)
-        self.course.display_name = u"Omega"
+        self.course.display_name = 'Omega'
         self.course = self.update_course(self.course, self.user.id)
 
-        download_url = 'www.edx.org'
-        GeneratedCertificateFactory.create(
+        cert = GeneratedCertificateFactory.create(
             user=self.user,
             course_id=self.course.id,
             status=CertificateStatuses.downloadable,
             mode='honor',
             grade='67',
-            download_url=download_url
+            download_url='https://www.edx.org'
         )
         response = self.client.get(reverse('dashboard'))
 
         self.assertEqual(response.status_code, 200)
         self.assertContains(response, 'Add Certificate to LinkedIn')
 
-        expected_url = (
-            u'http://www.linkedin.com/profile/add'
-            u'?_ed=0_mC_o2MizqdtZEmkVXjH4eYwMj4DnkCWrZP_D9&'
-            u'pfCertificationName={platform}+Honor+Code+Certificate+for+Omega&'
-            u'pfCertificationUrl=www.edx.org&'
-            u'source=o'
-        ).format(platform=quote(settings.PLATFORM_NAME.encode('utf-8')))
-
-        self.assertContains(response, escape(expected_url))
+        # We can switch to this and the commented out assertContains once edx-platform reaches Python 3.8
+        # expected_url = (
+        #     'https://www.linkedin.com/profile/add?startTask=CERTIFICATION_NAME&'
+        #     'name={platform}+Honor+Code+Certificate+for+Omega&certUrl={cert_url}&'
+        #     'organizationId={company_identifier}'
+        # ).format(
+        #     platform=quote(settings.PLATFORM_NAME.encode('utf-8')),
+        #     cert_url=quote(cert.download_url, safe=''),
+        #     company_identifier=linkedin_config.company_identifier,
+        # )
+
+        # self.assertContains(response, escape(expected_url))
+
+        # These can be removed (in favor of the above) once we are on Python 3.8. Fails in 3.5 because of dict ordering
+        self.assertContains(response, escape('https://www.linkedin.com/profile/add?startTask=CERTIFICATION_NAME'))
+        self.assertContains(response, escape('&name={platform}+Honor+Code+Certificate+for+Omega'.format(
+            platform=quote(settings.PLATFORM_NAME.encode('utf-8'))
+        )))
+        self.assertContains(response, escape('&certUrl={cert_url}'.format(cert_url=quote(cert.download_url, safe=''))))
+        self.assertContains(response, escape('&organizationId={company_identifier}'.format(
+            company_identifier=linkedin_config.company_identifier
+        )))
 
     @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
     @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
@@ -649,7 +658,7 @@ class EnrollmentEventTestMixin(EventTestMixin):
         self.mock_tracker.emit.assert_called_once_with(
             'edx.course.enrollment.mode_changed',
             {
-                'course_id': text_type(course_key),
+                'course_id': str(course_key),
                 'user_id': user.pk,
                 'mode': mode
             }
@@ -661,7 +670,7 @@ class EnrollmentEventTestMixin(EventTestMixin):
         self.mock_tracker.emit.assert_called_once_with(
             'edx.course.enrollment.activated',
             {
-                'course_id': text_type(course_key),
+                'course_id': str(course_key),
                 'user_id': user.pk,
                 'mode': CourseMode.DEFAULT_MODE_SLUG
             }
@@ -673,7 +682,7 @@ class EnrollmentEventTestMixin(EventTestMixin):
         self.mock_tracker.emit.assert_called_once_with(
             'edx.course.enrollment.deactivated',
             {
-                'course_id': text_type(course_key),
+                'course_id': str(course_key),
                 'user_id': user.pk,
                 'mode': CourseMode.DEFAULT_MODE_SLUG
             }
@@ -880,7 +889,7 @@ class ChangeEnrollmentViewTest(ModuleStoreTestCase):
         """ Enroll a student in a course. """
         response = self.client.post(
             reverse('change_enrollment'), {
-                'course_id': text_type(course.id),
+                'course_id': course.id,
                 'enrollment_action': 'enroll'
             }
         )
@@ -1020,7 +1029,7 @@ class RelatedProgramsTests(ProgramsApiConfigMixin, SharedModuleStoreTestCase):
         self.create_programs_config()
         self.client.login(username=self.user.username, password=self.password)
 
-        course_run = CourseRunFactory(key=six.text_type(self.course.id))  # pylint: disable=no-member
+        course_run = CourseRunFactory(key=str(self.course.id))  # pylint: disable=no-member
         course = CatalogCourseFactory(course_runs=[course_run])
         self.programs = [ProgramFactory(courses=[course]) for __ in range(2)]
 
@@ -1094,4 +1103,4 @@ class UserAttributeTests(TestCase):
     def test_unicode(self):
         UserAttribute.set_user_attribute(self.user, self.name, self.value)
         for field in (self.name, self.value, self.user.username):
-            self.assertIn(field, six.text_type(UserAttribute.objects.get(user=self.user)))
+            self.assertIn(field, str(UserAttribute.objects.get(user=self.user)))
diff --git a/lms/djangoapps/certificates/tests/factories.py b/lms/djangoapps/certificates/tests/factories.py
index 61df9af239221fadd588fbc3d057577099ea5345..c1dc63aedd92918ac903d68b44c85d144f2f390a 100644
--- a/lms/djangoapps/certificates/tests/factories.py
+++ b/lms/djangoapps/certificates/tests/factories.py
@@ -87,5 +87,4 @@ class LinkedInAddToProfileConfigurationFactory(DjangoModelFactory):
         model = LinkedInAddToProfileConfiguration
 
     enabled = True
-    company_identifier = "0_0dPSPyS070e0HsE9HNz_13_d11_"
-    trk_partner_name = 'unittest'
+    company_identifier = "1337"
diff --git a/lms/djangoapps/certificates/tests/test_webview_views.py b/lms/djangoapps/certificates/tests/test_webview_views.py
index 6857a3b03ed8aead4173333b3e77029f5d05a77d..1ce54771a99a1e93c2acf43746b216c40b14d8b2 100644
--- a/lms/djangoapps/certificates/tests/test_webview_views.py
+++ b/lms/djangoapps/certificates/tests/test_webview_views.py
@@ -14,8 +14,7 @@ from django.test.client import Client, RequestFactory
 from django.test.utils import override_settings
 from django.urls import reverse
 from mock import patch
-from six.moves import range
-from six.moves.urllib.parse import urlencode
+from urllib.parse import urlencode
 
 from course_modes.models import CourseMode
 from lms.djangoapps.badges.events.course_complete import get_completion_badge
@@ -97,7 +96,7 @@ class CommonCertificatesTestCase(ModuleStoreTestCase):
         self.user.profile.save()
         self.client.login(username=self.user.username, password='foo')
         self.request = RequestFactory().request()
-        self.linkedin_url = u'http://www.linkedin.com/profile/add?{params}'
+        self.linkedin_url = 'https://www.linkedin.com/profile/add?startTask=CERTIFICATION_NAME&{params}'
 
         self.cert = GeneratedCertificateFactory.create(
             user=self.user,
@@ -264,14 +263,17 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
         test_url = get_certificate_url(course_id=self.course.id, uuid=self.cert.verify_uuid)
         response = self.client.get(test_url)
         self.assertEqual(response.status_code, 200)
-        params = OrderedDict([
-            ('_ed', '0_0dPSPyS070e0HsE9HNz_13_d11_',),
-            ('pfCertificationName', u'{platform_name} Honor Code Certificate for {course_name}'.format(
-                platform_name=settings.PLATFORM_NAME,
-                course_name=self.course.display_name,
-            ).encode('utf-8'),),
-            ('pfCertificationUrl', self.request.build_absolute_uri(test_url),),
-        ])
+        params = {
+            'name': '{platform_name} Honor Code Certificate for {course_name}'.format(
+                platform_name=settings.PLATFORM_NAME, course_name=self.course.display_name,
+            ).encode('utf-8'),
+            'certUrl': self.request.build_absolute_uri(test_url),
+            # default value from the LinkedInAddToProfileConfigurationFactory company_identifier
+            'organizationId': 1337,
+            'certId': self.cert.verify_uuid,
+            'issueYear': self.cert.created_date.year,
+            'issueMonth': self.cert.created_date.month,
+        }
         self.assertContains(
             response,
             js_escaped_string(self.linkedin_url.format(params=urlencode(params))),
@@ -280,7 +282,7 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
     @override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
     @with_site_configuration(
         configuration={
-            'platform_name': 'My Platform Site', 'LINKEDIN_COMPANY_ID': 'test_linkedin_my_site',
+            'platform_name': 'My Platform Site', 'LINKEDIN_COMPANY_ID': 2448,
         },
     )
     def test_linkedin_share_url_site(self):
@@ -292,13 +294,16 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
         response = self.client.get(test_url, HTTP_HOST='test.localhost')
         self.assertEqual(response.status_code, 200)
         # the linkedIn share URL with appropriate parameters should be present
-        params = OrderedDict([
-            ('_ed', 'test_linkedin_my_site',),
-            ('pfCertificationName', u'My Platform Site Honor Code Certificate for {course_name}'.format(
+        params = {
+            'name': 'My Platform Site Honor Code Certificate for {course_name}'.format(
                 course_name=self.course.display_name,
-            ).encode('utf-8'),),
-            ('pfCertificationUrl', 'http://test.localhost' + test_url,),
-        ])
+            ).encode('utf-8'),
+            'certUrl': 'http://test.localhost' + test_url,
+            'organizationId': 2448,
+            'certId': self.cert.verify_uuid,
+            'issueYear': self.cert.created_date.year,
+            'issueMonth': self.cert.created_date.month,
+        }
         self.assertContains(
             response,
             js_escaped_string(self.linkedin_url.format(params=urlencode(params))),
diff --git a/lms/djangoapps/certificates/views/webview.py b/lms/djangoapps/certificates/views/webview.py
index 6b87a3982f624c58347fb03677f949bf30e80705..2957df6096603f889c9105c282f2ad1998da724a 100644
--- a/lms/djangoapps/certificates/views/webview.py
+++ b/lms/djangoapps/certificates/views/webview.py
@@ -291,13 +291,9 @@ def _update_social_context(request, context, course, user, user_certificate, pla
     # Clicking this button sends the user to LinkedIn where they
     # can add the certificate information to their profile.
     linkedin_config = LinkedInAddToProfileConfiguration.current()
-    linkedin_share_enabled = share_settings.get('CERTIFICATE_LINKEDIN', linkedin_config.enabled)
-    if linkedin_share_enabled:
+    if linkedin_config.is_enabled():
         context['linked_in_url'] = linkedin_config.add_to_profile_url(
-            course.id,
-            course.display_name,
-            user_certificate.mode,
-            smart_str(share_url)
+            course.display_name, user_certificate.mode, smart_str(share_url), certificate=user_certificate
         )
 
 
@@ -348,7 +344,8 @@ def _get_user_certificate(request, user, course_key, course, preview_mode=None):
             user_certificate = GeneratedCertificate(
                 mode=preview_mode,
                 verify_uuid=six.text_type(uuid4().hex),
-                modified_date=modified_date
+                modified_date=modified_date,
+                created_date=datetime.now().date(),
             )
     elif certificates_viewable_for_course(course):
         # certificate is being viewed by learner or public
diff --git a/openedx/core/djangoapps/courseware_api/serializers.py b/openedx/core/djangoapps/courseware_api/serializers.py
index b3396aaff50030fbf2f1c3ffed0c5f72a1c66aff..be2164e5d1c4972f783eba1e813dd9b35d557650 100644
--- a/openedx/core/djangoapps/courseware_api/serializers.py
+++ b/openedx/core/djangoapps/courseware_api/serializers.py
@@ -95,6 +95,7 @@ class CourseInfoSerializer(serializers.Serializer):  # pylint: disable=abstract-
     course_exit_page_is_active = serializers.BooleanField()
     certificate_data = CertificateDataSerializer()
     verify_identity_url = AbsoluteURLField()
+    linkedin_add_to_profile_url = serializers.URLField()
 
     def __init__(self, *args, **kwargs):
         """
diff --git a/openedx/core/djangoapps/courseware_api/tests/test_views.py b/openedx/core/djangoapps/courseware_api/tests/test_views.py
index 908a00086a51525a8933ec90375b975eb90c3191..e84b66a76834c5b4ebff550647d4b43991744806 100644
--- a/openedx/core/djangoapps/courseware_api/tests/test_views.py
+++ b/openedx/core/djangoapps/courseware_api/tests/test_views.py
@@ -3,13 +3,19 @@ Tests for courseware API
 """
 import unittest
 from datetime import datetime
+from urllib.parse import urlencode
 
 import ddt
 import mock
 from completion.test_utils import CompletionWaffleTestMixin, submit_completions_for_testing
 from django.conf import settings
+from django.test.client import RequestFactory
 from django.urls import reverse
 
+from lms.djangoapps.certificates.api import get_certificate_url
+from lms.djangoapps.certificates.tests.factories import (
+    GeneratedCertificateFactory, LinkedInAddToProfileConfigurationFactory
+)
 from lms.djangoapps.courseware.access_utils import ACCESS_DENIED, ACCESS_GRANTED
 from lms.djangoapps.courseware.tabs import ExternalLinkCourseTab
 from lms.djangoapps.courseware.tests.helpers import MasqueradeMixin
@@ -73,6 +79,7 @@ class CourseApiTestViews(BaseCoursewareTests):
             ExternalLinkCourseTab.load('external_link', name='Hidden', link='http://hidden.com', is_hidden=True)
         )
         cls.store.update_item(cls.course, cls.user.id)
+        LinkedInAddToProfileConfigurationFactory.create()
 
     @ddt.data(
         (True, None, ACCESS_DENIED),
@@ -82,6 +89,7 @@ class CourseApiTestViews(BaseCoursewareTests):
         (False, None, ACCESS_GRANTED),
     )
     @ddt.unpack
+    @mock.patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': True})
     @mock.patch('openedx.core.djangoapps.courseware_api.views.CoursewareMeta.is_microfrontend_enabled_for_user')
     def test_course_metadata(self, logged_in, enrollment_mode, enable_anonymous, is_microfrontend_enabled_for_user):
         is_microfrontend_enabled_for_user.return_value = True
@@ -92,6 +100,14 @@ class CourseApiTestViews(BaseCoursewareTests):
                 self.client.logout()
             if enrollment_mode:
                 CourseEnrollment.enroll(self.user, self.course.id, enrollment_mode)
+            if enrollment_mode == 'verified':
+                cert = GeneratedCertificateFactory.create(
+                    user=self.user,
+                    course_id=self.course.id,
+                    status='downloadable',
+                    mode='verified',
+                )
+
             response = self.client.get(self.url)
             assert response.status_code == 200
             if enrollment_mode:
@@ -114,12 +130,32 @@ class CourseApiTestViews(BaseCoursewareTests):
                                               'The audit track does not include a certificate.')
                     assert response.data['certificate_data']['msg'] == expected_audit_message
                     assert response.data['verify_identity_url'] is None
+                    assert response.data['linkedin_add_to_profile_url'] is None
                 else:
-                    # Not testing certificate data for verified learner here. That is tested elsewhere
-                    assert response.data['certificate_data'] is None
+                    assert response.data['certificate_data']['cert_status'] == 'earned_but_not_available'
                     expected_verify_identity_url = reverse('verify_student_verify_now', args=[self.course.id])
                     # The response contains an absolute URL so this is only checking the path of the final
                     assert expected_verify_identity_url in response.data['verify_identity_url']
+
+                    request = RequestFactory().request()
+                    cert_url = get_certificate_url(course_id=self.course.id, uuid=cert.verify_uuid)
+                    linkedin_url_params = {
+                        'name': '{platform_name} Verified Certificate for {course_name}'.format(
+                            platform_name=settings.PLATFORM_NAME, course_name=self.course.display_name,
+                        ),
+                        'certUrl': request.build_absolute_uri(cert_url),
+                        # default value from the LinkedInAddToProfileConfigurationFactory company_identifier
+                        'organizationId': 1337,
+                        'certId': cert.verify_uuid,
+                        'issueYear': cert.created_date.year,
+                        'issueMonth': cert.created_date.month,
+                    }
+                    expected_linkedin_url = (
+                        'https://www.linkedin.com/profile/add?startTask=CERTIFICATION_NAME&{params}'.format(
+                            params=urlencode(linkedin_url_params)
+                        )
+                    )
+                    assert response.data['linkedin_add_to_profile_url'] == expected_linkedin_url
             elif enable_anonymous and not logged_in:
                 # multiple checks use this handler
                 check_public_access.assert_called()
diff --git a/openedx/core/djangoapps/courseware_api/views.py b/openedx/core/djangoapps/courseware_api/views.py
index 09bc763617c450662e176ef615ffc93d402e92f4..3c8f9f4b85a58df7fb598a72534bf41a0c7aa1fc 100644
--- a/openedx/core/djangoapps/courseware_api/views.py
+++ b/openedx/core/djangoapps/courseware_api/views.py
@@ -21,6 +21,8 @@ from rest_framework.views import APIView
 
 from course_modes.models import CourseMode
 from lms.djangoapps.edxnotes.helpers import is_feature_enabled
+from lms.djangoapps.certificates.api import get_certificate_url
+from lms.djangoapps.certificates.models import GeneratedCertificate
 from lms.djangoapps.course_api.api import course_detail
 from lms.djangoapps.courseware.access import has_access
 from lms.djangoapps.courseware.access_response import (
@@ -41,7 +43,7 @@ from openedx.features.course_experience import DISPLAY_COURSE_SOCK_FLAG
 from openedx.features.content_type_gating.models import ContentTypeGatingConfig
 from openedx.features.course_duration_limits.access import generate_course_expired_message
 from openedx.features.discounts.utils import generate_offer_html
-from student.models import CourseEnrollment, CourseEnrollmentCelebration
+from student.models import CourseEnrollment, CourseEnrollmentCelebration, LinkedInAddToProfileConfiguration
 from xmodule.modulestore.django import modulestore
 from xmodule.modulestore.search import path_to_location
 
@@ -53,15 +55,16 @@ class CoursewareMeta:
     Encapsulates courseware and enrollment metadata.
     """
     def __init__(self, course_key, request, username=''):
+        self.request = request
         self.overview = course_detail(
-            request,
-            username or request.user.username,
+            self.request,
+            username or self.request.user.username,
             course_key,
         )
-        self.original_user_is_staff = has_access(request.user, 'staff', self.overview).has_access
+        self.original_user_is_staff = has_access(self.request.user, 'staff', self.overview).has_access
         self.course_key = course_key
         self.course_masquerade, self.effective_user = setup_masquerade(
-            request,
+            self.request,
             course_key,
             staff_access=self.original_user_is_staff,
         )
@@ -246,6 +249,32 @@ class CoursewareMeta:
             else:
                 return IDVerificationService.get_verify_location('verify_student_verify_now', self.course_key)
 
+    @property
+    def linkedin_add_to_profile_url(self):
+        """
+        Returns a URL to add a certificate to a LinkedIn profile (will autofill fields).
+
+        Requires LinkedIn sharing to be enabled, either via a site configuration or a
+        LinkedInAddToProfileConfiguration object being enabled.
+        """
+        if self.effective_user.is_anonymous:
+            return
+
+        linkedin_config = LinkedInAddToProfileConfiguration.current()
+        if linkedin_config.is_enabled():
+            try:
+                user_certificate = GeneratedCertificate.eligible_certificates.get(
+                    user=self.effective_user, course_id=self.course_key
+                )
+            except GeneratedCertificate.DoesNotExist:
+                return
+            cert_url = self.request.build_absolute_uri(
+                get_certificate_url(course_id=self.course_key, uuid=user_certificate.verify_uuid)
+            )
+            return linkedin_config.add_to_profile_url(
+                self.overview.display_name, user_certificate.mode, cert_url, certificate=user_certificate,
+            )
+
 
 class CoursewareInformation(RetrieveAPIView):
     """
@@ -296,6 +325,7 @@ class CoursewareInformation(RetrieveAPIView):
         * certificate_data: data regarding the effective user's certificate for the given course
         * verify_identity_url: URL for a learner to verify their identity. Only returned for learners enrolled in a
             verified mode. Will update to reverify URL if necessary.
+        * linkedin_add_to_profile_url: URL to add the effective user's certificate to a LinkedIn Profile.
 
     **Parameters:**
 
diff --git a/openedx/core/djangoapps/user_authn/views/tests/test_login.py b/openedx/core/djangoapps/user_authn/views/tests/test_login.py
index 7220771e84ff2d0f780eb1c0b72517f5ccb5bf0c..718d213363805164933e53eb6affa4b6e74cc1ee 100644
--- a/openedx/core/djangoapps/user_authn/views/tests/test_login.py
+++ b/openedx/core/djangoapps/user_authn/views/tests/test_login.py
@@ -19,7 +19,6 @@ from django.test.client import Client
 from django.test.utils import override_settings
 from django.urls import NoReverseMatch, reverse
 from mock import patch
-from six.moves import range
 
 from openedx.core.djangoapps.password_policy.compliance import (
     NonCompliantPasswordException,