class AnalyticsReportsAssignmentForm(group.GroupForm):
    label = _(u'analytics_assignment', default=u'Reports')
    description = _(
        u'analytics_assignment_description',
        default=(u'Configure the reports that are displayed in the Google '
                 u'Analytics control panel.'))
    fields = field.Fields(IAnalyticsReportsAssignment)
class AnalyticsTrackingForm(group.GroupForm):
    fields = field.Fields(IAnalyticsTracking)
    label = _(u'analytics_tracking', default=u'Tracking')
    description = _(
        u'analytics_tracking_description',
        default=(u'Configure the way Google Analytics tracks statistics '
                 u'about this site.'))
    def __call__(self):
        """
        Gets the token from the URL and takes the appropriate action.
        """

        analytics_tool = getToolByName(self.context, "portal_analytics")
        plone_utils = getToolByName(self.context, "plone_utils")
        clients = analytics_tool.getClients()

        # Check if we are revoking the token.
        if self.request.get("revoke_token", 0):
            analytics_tool.auth_token = None
            try:
                clients.data.RevokeAuthSubToken()
            except NonAuthSubToken:
                # Authorization already revoked
                pass

            message = _(
                u"Authorization revoked. You may now reauthorize with \
                a different Google account."
            )
            plone_utils.addPortalMessage(message)

        # Otherwise, we are setting the token.
        elif self.request.QUERY_STRING and "token" in self.request:
            current_url = "%s?%s" % (self.request.ACTUAL_URL, self.request.QUERY_STRING)
            single_token = gdata.auth.extract_auth_sub_token_from_url(current_url)

            try:
                session_token = clients.data.upgrade_to_session_token(single_token)

                # Save a string representation of the token.
                analytics_tool.auth_token = unicode(session_token.get_token_string())

                # Set the token on the two servcies using SetAuthSubToken.
                clients.data.SetAuthSubToken(session_token)
                clients.accounts.SetAuthSubToken(session_token)

                message = _(
                    u"Authorization succeeded. You may now configure \
                Google Analytics for Plone."
                )

            except TokenUpgradeFailed:
                message = _(
                    u"Authorization failed. Google Analytics for \
                    Plone received an invalid token."
                )

            plone_utils.addPortalMessage(message)

        # Redirect back to the control panel.
        portal_url = getToolByName(self.context, "portal_url")
        next_url = "%s/portal_analytics/@@analytics-controlpanel" % portal_url()
        self.request.response.redirect(next_url)
class EditForm(base.EditForm):
    """Portlet edit form.

    This is registered with configure.zcml. The form_fields variable tells
    zope.formlib which fields to display.
    """
    schema = IAnalyticsPortlet

    label = _(u'Add Analytics Portlet')
    description = _(u'')
def getPossibleDateRanges(context):
    """
    Return the possible date ranges
    """
    vocab = [
        SimpleTerm('week', 'week', _(u"Week")),
        SimpleTerm('month', 'month', _(u"Month")),
        SimpleTerm('quarter', 'quarter', _(u"Quarter")),
        SimpleTerm('year', 'year', _(u"Year")),
    ]

    return SimpleVocabulary(vocab)
Exemplo n.º 6
0
    def __call__(self):
        """
        Gets the token from the URL and takes the appropriate action.
        """
        
        analytics_tool = getToolByName(self.context, 'portal_analytics')
        plone_utils = getToolByName(self.context, 'plone_utils')
        clients = analytics_tool.getClients()
        
        # Check if we are revoking the token.
        if self.request.get('revoke_token', 0):
            analytics_tool.auth_token = None
            try:
                clients.data.RevokeAuthSubToken()
            except NonAuthSubToken:
                # Authorization already revoked
                pass
                
            message = _(u'Authorization revoked. You may now reauthorize with \
                a different Google account.')
            plone_utils.addPortalMessage(message)
            
        # Otherwise, we are setting the token.
        elif self.request.QUERY_STRING and 'token' in self.request:
            current_url = '%s?%s' % (self.request.ACTUAL_URL, self.request.QUERY_STRING)
            single_token = gdata.auth.extract_auth_sub_token_from_url(current_url)
            
            try:
                session_token = clients.data.upgrade_to_session_token(single_token)

                # Save a string representation of the token.
                analytics_tool.auth_token = unicode(session_token.get_token_string())

                # Set the token on the two servcies using SetAuthSubToken.
                clients.data.SetAuthSubToken(session_token)
                clients.accounts.SetAuthSubToken(session_token)
            
                message = _(u'Authorization succeeded. You may now configure \
                Google Analytics for Plone.')
                
            except TokenUpgradeFailed:
                message = _(u'Authorization failed. Google Analytics for \
                    Plone received an invalid token.')
                
            plone_utils.addPortalMessage(message)
            
        # Redirect back to the control panel.
        portal_url = getToolByName(self.context, 'portal_url')
        next_url = '%s/portal_analytics/@@analytics-controlpanel' % portal_url()
        self.request.response.redirect(next_url)
        
class AddForm(base.AddForm):
    """Portlet add form.

    This is registered in configure.zcml. The form_fields variable tells
    zope.formlib which fields to display. The create() method actually
    constructs the assignment that is being added.
    """
    schema = IAnalyticsPortlet

    label = _(u'Add Analytics Portlet')
    description = _(u'')

    def create(self, data):
        return Assignment(**data)
 def extractData(self, setErrors=True):
     """
     Checks to make sure that tracking code is not duplicated in the site
     configlet.
     """
     data, errors = super(AnalyticsControlPanelForm, self).extractData(
         setErrors=setErrors
     )
     tracking_web_property = data.get('tracking_web_property', None)
     if HAS_PLONE5:
         registry = getUtility(IRegistry)
         site_records = registry.forInterface(ISiteSchema, prefix='plone')
         snippet = site_records.webstats_js
     else:   # Plone 4 stores the analytics script in the properties
         properties_tool = api.portal.get_tool(name="portal_properties")
         snippet = properties_tool.site_properties.webstats_js
     snippet = snippet or ''
     snippet_analytics = '_gat' in snippet or '_gaq' in snippet
     if tracking_web_property and snippet_analytics:
         api.portal.show_message(
             _(u"You have enabled the tracking feature of this product, "
               u"but it looks like you still have tracking code in the "
               u"Site control panel. Please remove any Google Analytics "
               u"tracking code from the Site control panel to avoid "
               u"conflicts.'"), self.request, type='warning')
     return data, errors
Exemplo n.º 9
0
    def __call__(self):
        """
        Gets the token from the URL and takes the appropriate action.
        """
        alsoProvides(self.request, IDisableCSRFProtection)

        analytics_tool = getToolByName(self.context, 'portal_analytics')
        plone_utils = getToolByName(self.context, 'plone_utils')

        # Check if we are revoking the token.
        if self.request.get('revoke_token', 0):
            analytics_tool.revoke_token()
            message = _(u'Authorization revoked. You may now reauthorize with \
                a different Google account.')
            plone_utils.addPortalMessage(message)

        # Otherwise, we are setting the token.
        elif self.request.QUERY_STRING and 'code' in self.request:
            code = self.request.get('code')
            message = analytics_tool.set_token(code)
            plone_utils.addPortalMessage(message)

        # Redirect back to the control panel.
        portal_url = getToolByName(self.context, 'portal_url')
        next_url = '%s/portal_analytics/@@analytics-controlpanel' % portal_url()
        self.request.response.redirect(next_url)
Exemplo n.º 10
0
    def __call__(self):
        """
        Returns a list of AnalyticsReportResults objects
        for the selected reports.
        """

        report_ids = self.request.get('report_ids', '').split(',')

        if not report_ids:
            return []

        analytics_tool = getToolByName(self.context, 'portal_analytics')

        results = []
        for report_id in report_ids:
            try:
                report = analytics_tool[report_id]
            except KeyError:
                continue

            try:
                renderer = getMultiAdapter(
                    (self.context, self.request, report),
                    interface=IAnalyticsReportRenderer
                )
                results.append(renderer())
            except error.BadAuthenticationError:
                return self.bad_auth()
            except error.RequestTimedOutError:
                return self.timed_out()

        date_range_msg = _('Last %s' % analytics_tool.date_range)
        return '<h2>%s</h2>' % (
            self.context.translate(date_range_msg)) + '\n'.join(results)
Exemplo n.º 11
0
    def __call__(self):
        """
        Gets the token from the URL and takes the appropriate action.
        """
        alsoProvides(self.request, IDisableCSRFProtection)

        analytics_tool = getToolByName(self.context, 'portal_analytics')
        plone_utils = getToolByName(self.context, 'plone_utils')

        # Check if we are revoking the token.
        if self.request.get('revoke_token', 0):
            analytics_tool.revoke_token()
            message = _(u'Authorization revoked. You may now reauthorize with \
                a different Google account.')
            plone_utils.addPortalMessage(message)

        # Otherwise, we are setting the token.
        elif self.request.QUERY_STRING and 'code' in self.request:
            code = self.request.get('code')
            message = analytics_tool.set_token(code)
            plone_utils.addPortalMessage(message)

        # Redirect back to the control panel.
        portal_url = getToolByName(self.context, 'portal_url')
        next_url = '%s/portal_analytics/@@analytics-controlpanel' % portal_url(
        )
        self.request.response.redirect(next_url)
Exemplo n.º 12
0
    def __call__(self):
        """
        Returns a list of AnalyticsReportResults objects for the selected reports.
        """

        report_ids = self.request.get('report_ids', '').split(',')

        if not report_ids:
            return []

        analytics_tool = getToolByName(self.context, 'portal_analytics')

        results = []
        for report_id in report_ids:
            try:
                report = analytics_tool[report_id]
            except KeyError:
                continue

            try:
                renderer = getMultiAdapter(
                    (self.context, self.request, report),
                    interface=IAnalyticsReportRenderer)
                results.append(renderer())
            except error.BadAuthenticationError:
                return self.bad_auth()
            except error.RequestTimedOutError:
                return self.timed_out()

        # Once we expose the date range optoin in the UI, we'll need to find a
        # way to generate this label dynamically, probably by using the variable
        # date range plugin from one of the report renderers.
        date_range_msg = _('Last 30 Days')
        return '<h2>%s</h2>' % (
            self.context.translate(date_range_msg)) + '\n'.join(results)
 def extractData(self, setErrors=True):
     """
     Checks to make sure that tracking code is not duplicated in the site
     configlet.
     """
     data, errors = super(AnalyticsControlPanelForm,
                          self).extractData(setErrors=setErrors)
     tracking_web_property = data.get('tracking_web_property', None)
     if HAS_PLONE5:
         registry = getUtility(IRegistry)
         site_records = registry.forInterface(ISiteSchema, prefix='plone')
         snippet = site_records.webstats_js
     else:  # Plone 4 stores the analytics script in the properties
         properties_tool = api.portal.get_tool(name="portal_properties")
         snippet = properties_tool.site_properties.webstats_js
     snippet = snippet or ''
     snippet_analytics = '_gat' in snippet or '_gaq' in snippet
     if tracking_web_property and snippet_analytics:
         api.portal.show_message(_(
             u"You have enabled the tracking feature of this product, "
             u"but it looks like you still have tracking code in the "
             u"Site control panel. Please remove any Google Analytics "
             u"tracking code from the Site control panel to avoid "
             u"conflicts.'"),
                                 self.request,
                                 type='warning')
     return data, errors
Exemplo n.º 14
0
 def __call__(self):
     """
     Returns a list of AnalyticsReportResults objects for the selected reports.
     """
             
     report_ids = self.request.get('report_ids', '').split(',')
     
     if not report_ids:
         return []
         
     analytics_tool = getToolByName(self.context, 'portal_analytics')
     
     results = []
     for report_id in report_ids:
         try:
             report = analytics_tool[report_id]
         except KeyError:
             continue
             
         try:
             renderer = getMultiAdapter(
                 (self.context, self.request, report),
                 interface=IAnalyticsReportRenderer
             )
             results.append(renderer())
         except error.BadAuthenticationError:
             return self.bad_auth()
         except error.RequestTimedOutError:
             return self.timed_out()
             
     # Once we expose the date range optoin in the UI, we'll need to find a
     # way to generate this label dynamically, probably by using the variable
     # date range plugin from one of the report renderers.
     date_range_msg = _('Last 30 Days')
     return '<h2>%s</h2>'%(self.context.translate(date_range_msg)) + '\n'.join(results)
Exemplo n.º 15
0
def getWebProperties(context):
    """
    Return list of Google Analytics profiles and web property
    IDs (e.g. UA-30481-22).
    """

    custom_connection = (_(u'custom tracking code'), '_TRACKING_CODE_CUSTOM')

    analytics_tool = getToolByName(getSite(), 'portal_analytics')
    # short circuit if user hasn't authorized yet
    if not analytics_tool.auth_token:
        return SimpleVocabulary([
            SimpleTerm(custom_connection[1], custom_connection[1],
                       custom_connection[0])
        ])

    try:
        accounts = analytics_tool.getAccountsFeed(
            'accounts/~all/webproperties/~all/profiles')
    except error.BadAuthenticationError:
        choices = [('Please authorize with Google in the Google Analytics \
            control panel.', None)]
        return SimpleVocabulary.fromItems(choices)
    except error.RequestTimedOutError:
        choices = [('The request to Google Analytics timed out. Please try \
            again later.', None)]
        return SimpleVocabulary.fromItems(choices)
    if accounts:
        unique_choices = {}
        # In vocabularies, both the terms and the values must be unique. Since
        # there can be more than one profile for a given web property, we create a list
        # of all the profiles for each property. (Ideally we would use the URL for the
        # web property, but Google doesn't expose it through the Analytics API.)
        for entry in accounts.entry:
            for prop in entry.property:
                if prop.name == 'ga:profileName':
                    title = prop.value
                    if not isinstance(title, unicode):
                        title = unicode(title, 'utf-8')
                if prop.name == 'ga:webPropertyId':
                    webPropertyId = prop.value
            if not webPropertyId in unique_choices.keys():
                unique_choices.update({webPropertyId: title})
            else:
                unique_choices[webPropertyId] += ', ' + title
        # After we reverse the terms so that the profile name(s) is now the key, we need
        # to ensure that these keys are unique. So, we pass the resulting list through
        # dict() and then output a list of items.
        choices = dict([(crop(title, 40), property_id)
                        for (property_id, title) in unique_choices.items()
                        ]).items()
    else:
        choices = [('No profiles available', None)]
    choices.append(custom_connection)
    return SimpleVocabulary([SimpleTerm(c[1], c[1], c[0]) for c in choices])
Exemplo n.º 16
0
    def __call__(self):
        """
        gets the code from URL
        gets the credentials based on flow and code
        gets OAuth2 token from credentials
        takes the appropriate action
        """
        code = self.context.REQUEST.form.get('code', None)

        analytics_tool = getToolByName(self.context, 'portal_analytics')
        plone_utils = getToolByName(self.context, 'plone_utils')
        clients = analytics_tool.getClients()

        # Check if we are revoking the token.
        if self.request.get('revoke_token', 0):
            analytics_tool.auth_token = None

            clients.data = ''

            message = _(u'Authorization revoked. You may now reauthorize with \
                a different Google account.')
            plone_utils.addPortalMessage(message)

        # Otherwise, we are setting the token.
        elif code is not None:
            flow = get_flow()
            credentials = flow.step2_exchange(code)
            token_response = credentials.token_response
            access_token = token_response.get('access_token')
            analytics_tool.auth_token = access_token
            clients.data = gdata.analytics.service.AnalyticsDataService()
            clients.accounts = gdata.analytics.service.AccountsService()

            message = _(u'Authorization succeeded. You may now configure \
            Google Analytics for Plone.')
            plone_utils.addPortalMessage(message)

        # Redirect back to the control panel.
        portal_url = getToolByName(self.context, 'portal_url')
        next_url = '%s/portal_analytics/@@analytics-controlpanel' % \
            portal_url()
        self.request.response.redirect(next_url)
class IAnalyticsPortlet(IPortletDataProvider):
    """A portlet

    It inherits from IPortletDataProvider because for this portlet, the
    data that is being rendered and the portlet assignment itself are the
    same.
    """

    portlet_title = schema.TextLine(
        title=_(u'Title'),
        description=_(u'Enter the title of the portlet.'),
        required=True,
        default=u'Google Analytics')

    profile = schema.Choice(
        title=_(u"Profile"),
        vocabulary='collective.googleanalytics.Profiles',
        description=_(
            u"Choose the Web property profile from Google Analytics."),
        required=True)

    reports = schema.List(
        title=_(u"Reports"),
        value_type=schema.Choice(
            vocabulary='collective.googleanalytics.PortletReports'),
        min_length=1,
        description=_(u"Choose the reports to display."),
        required=True)
Exemplo n.º 18
0
def getWebProperties(context):
    """
    Return list of Google Analytics profiles and web property
    IDs (e.g. UA-30481-22).
    """

    custom_connection = (_(u'custom tracking code'), '_TRACKING_CODE_CUSTOM')

    analytics_tool = getToolByName(getSite(), 'portal_analytics')
    # short circuit if user hasn't authorized yet
    if not analytics_tool.auth_token:
        return SimpleVocabulary([SimpleTerm(custom_connection[1],
                                            custom_connection[1],
                                            custom_connection[0])])

    try:
        accounts = analytics_tool.getAccountsFeed('accounts/~all/webproperties/~all/profiles')
    except error.BadAuthenticationError:
        choices = [('Please authorize with Google in the Google Analytics \
            control panel.', None)]
        return SimpleVocabulary.fromItems(choices)
    except error.RequestTimedOutError:
        choices = [('The request to Google Analytics timed out. Please try \
            again later.', None)]
        return SimpleVocabulary.fromItems(choices)
    if accounts:
        unique_choices = {}
        # In vocabularies, both the terms and the values must be unique. Since
        # there can be more than one profile for a given web property, we create a list
        # of all the profiles for each property. (Ideally we would use the URL for the
        # web property, but Google doesn't expose it through the Analytics API.)
        for entry in accounts.entry:
            for prop in entry.property:
                if prop.name == 'ga:profileName':
                    title = prop.value
                    if not isinstance(title, unicode):
                        title = unicode(title, 'utf-8')
                if prop.name == 'ga:webPropertyId':
                    webPropertyId = prop.value
            if not webPropertyId in unique_choices.keys():
                unique_choices.update({webPropertyId : title})
            else:
                unique_choices[webPropertyId] += ', ' + title
        # After we reverse the terms so that the profile name(s) is now the key, we need
        # to ensure that these keys are unique. So, we pass the resulting list through
        # dict() and then output a list of items.
        choices = dict([(crop(title, 40), property_id) for (property_id, title) in unique_choices.items()]).items()
    else:
        choices = [('No profiles available', None)]
    choices.append(custom_connection)
    return SimpleVocabulary([SimpleTerm(c[1], c[1], c[0]) for c in choices])
Exemplo n.º 19
0
 def _on_save(self, data={}):
     """
     Checks to make sure that tracking code is not duplicated in the site
     configlet.
     """
     
     tracking_web_property = data.get('tracking_web_property', None)
     properties_tool = getToolByName(self.context, "portal_properties")
     snippet = properties_tool.site_properties.webstats_js
     snippet_analytics =  '_gat' in snippet or '_gaq' in snippet
     if tracking_web_property and snippet_analytics:
         plone_utils = getToolByName(self.context, 'plone_utils')
         plone_utils.addPortalMessage(_(u'You have enabled the tracking \
         feature of this product, but it looks like you still have tracking \
         code in the Site control panel. Please remove any Google Analytics \
         tracking code from the Site control panel to avoid conflicts.'),
         'warning')
Exemplo n.º 20
0
    def _on_save(self, data={}):
        """
        Checks to make sure that tracking code is not duplicated in the site
        configlet.
        """

        tracking_web_property = data.get('tracking_web_property', None)
        properties_tool = getToolByName(self.context, "portal_properties")
        snippet = properties_tool.site_properties.webstats_js
        snippet_analytics = '_gat' in snippet or '_gaq' in snippet
        if tracking_web_property and snippet_analytics:
            plone_utils = getToolByName(self.context, 'plone_utils')
            plone_utils.addPortalMessage(
                _(u'You have enabled the tracking \
            feature of this product, but it looks like you still have tracking \
            code in the Site control panel. Please remove any Google Analytics \
            tracking code from the Site control panel to avoid conflicts.'),
                'warning')
Exemplo n.º 21
0
    def __call__(self):
        """
        Gets the token from the URL and takes the appropriate action.
        """

        analytics_tool = getToolByName(self.context, "portal_analytics")
        plone_utils = getToolByName(self.context, "plone_utils")

        # Check if we are revoking the token.
        if self.request.get("revoke_token", 0):
            logger.debug("Trying to revoke token")
            ann = IAnnotations(analytics_tool)
            try:
                oauth2_token = ann.get("auth_token", None)
                if oauth2_token:
                    oauth2_token.revoke()
                    logger.debug("Token revoked successfuly")
            except OAuth2RevokeError:
                # Authorization already revoked
                logger.debug("Token was already revoked")
                pass
            except socket.gaierror:
                logger.debug("There was a connection issue, could not revoke " "token.")
                raise error.RequestTimedOutError, ("You may not have internet access. Please try again " "later.")

            ann["auth_token"] = None
            ann["valid_token"] = False

            message = _(
                u"Authorization revoked. You may now reauthorize with \
                a different Google account."
            )
            plone_utils.addPortalMessage(message)

        # Otherwise, we are setting the token.
        elif self.request.QUERY_STRING and "code" in self.request:
            code = self.request.get("code")
            logger.debug("Received callback from Google with code '%s' " % code)
            ann = IAnnotations(analytics_tool)
            oauth2_token = ann.get("auth_token", None)
            try:
                oauth2_token.get_access_token(code)
                logger.debug(
                    "Code was valid, got '%s' as access_token and '%s' as "
                    "refresh_token. Token will expire on '%s'"
                    % (oauth2_token.access_token, oauth2_token.refresh_token, oauth2_token.token_expiry)
                )
                message = _(
                    u"Authorization succeeded. You may now configure \
                Google Analytics for Plone."
                )
                ann["valid_token"] = True

            except OAuth2AccessTokenError:
                logger.debug("Code was invalid, could not get tokens")
                ann["auth_token"] = None
                ann["valid_token"] = False
                message = _(
                    u"Authorization failed. Google Analytics for \
                    Plone received an invalid token."
                )

            plone_utils.addPortalMessage(message)

        # Redirect back to the control panel.
        portal_url = getToolByName(self.context, "portal_url")
        next_url = "%s/portal_analytics/@@analytics-controlpanel" % portal_url()
        self.request.response.redirect(next_url)
class AnalyticsSettingsForm(group.GroupForm):
    fields = field.Fields(IAnalyticsSettings)
    label = _(u'analytics_settings', default=u'Settings')
    description = _(
        u'analytics_settings_description',
        default=u'Configure the settings of the Google Analytics product.')
Exemplo n.º 23
0
class AnalyticsControlPanelForm(ControlPanelForm):
    """
    Google Analytics Control Panel Form
    """

    implements(IAnalyticsControlPanelForm)
    template = ViewPageTemplateFile('controlpanel.pt')

    analytics_assignment = FormFieldsets(IAnalyticsReportsAssignment)
    analytics_assignment.id = 'analytics_assignment'
    analytics_assignment.label = _(u'analytics_assignment', default=u'Reports')
    analytics_assignment.description = _(
        u'analytics_assignment_description',
        default=
        u'Configure the reports that are displayed in the Google Analytics control panel.'
    )
    analytics_assignment[
        'reports'].custom_widget = MultiCheckBoxVocabularyWidget

    analytics_tracking = FormFieldsets(IAnalyticsTracking)
    analytics_tracking.id = 'analytics_tracking'
    analytics_tracking.label = _(u'analytics_tracking', default=u'Tracking')
    analytics_tracking.description = _(
        u'analytics_tracking_description',
        default=
        u'Configure the way Google Analytics tracks statistics about this site.'
    )
    analytics_tracking[
        'tracking_plugin_names'].custom_widget = MultiCheckBoxVocabularyWidget
    analytics_tracking[
        'tracking_excluded_roles'].custom_widget = MultiCheckBoxVocabularyWidget

    analytics_settings = FormFieldsets(IAnalyticsSettings)
    analytics_settings.id = 'analytics_settings'
    analytics_settings.label = _(u'analytics_settings', default=u'Settings')
    analytics_settings.description = _(
        u'analytics_settings_description',
        default=u'Configure the settings of the Google Analytics product.')

    form_fields = FormFieldsets(analytics_tracking, analytics_assignment,
                                analytics_settings)

    label = _(u"Google Analytics")
    form_name = _("Google Analytics Settings")

    def authorized(self):
        """
        Returns True if we have an auth token, or false otherwise.
        """

        if self.context.auth_token:
            return True
        return False

    def auth_url(self):
        """
        Returns the URL used to retrieve a Google AuthSub token.
        """

        next = '%s/analytics-auth' % self.context.portal_url()
        scope = 'https://www.google.com/analytics/feeds/'
        return gdata.auth.GenerateAuthSubUrl(next,
                                             scope,
                                             secure=False,
                                             session=True)

    def account_name(self):
        """
        Returns the account name for the currently authorized account.
        """

        analytics_tool = getToolByName(self.context, 'portal_analytics')

        try:
            res = analytics_tool.getAccountsFeed('accounts')
        except error.BadAuthenticationError:
            return None
        except error.RequestTimedOutError:
            return None
        return res.title.text.split(' ')[-1]

    def _on_save(self, data={}):
        """
        Checks to make sure that tracking code is not duplicated in the site
        configlet.
        """

        tracking_web_property = data.get('tracking_web_property', None)
        properties_tool = getToolByName(self.context, "portal_properties")
        snippet = properties_tool.site_properties.webstats_js
        snippet_analytics = '_gat' in snippet or '_gaq' in snippet
        if tracking_web_property and snippet_analytics:
            plone_utils = getToolByName(self.context, 'plone_utils')
            plone_utils.addPortalMessage(
                _(u'You have enabled the tracking \
            feature of this product, but it looks like you still have tracking \
            code in the Site control panel. Please remove any Google Analytics \
            tracking code from the Site control panel to avoid conflicts.'),
                'warning')