Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add analytics events #1036

Merged
merged 15 commits into from
Jun 21, 2017
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ Lock will emit events during its lifecycle.
- `authenticated`: emitted after a successful authentication. Has the authentication result as the only argument.
- `authorization_error`: emitted when authorization fails. Has error as the only argument.
- `hash_parsed`: every time a new Auth0Lock object is initialized in redirect mode (the default), it will attempt to parse the hash part of the url looking for the result of a login attempt. This is a _low level_ event for advanced use cases and _authenticated_ and _authorization_error_ should be preferred when possible. After that this event will be emitted with `null` if it couldn't find anything in the hash. It will be emitted with the same argument as the `authenticated` event after a successful login or with the same argument as `authorization_error` if something went wrong. This event won't be emitted in popup mode because there is no need to parse the url's hash part.
- `forgot_password ready`: emitted when the "Forgot password" screen is shown.
- `forgot_password submit`: emitted when the user clicks on the submit button of the "Forgot password" screen.
- `signin submit`: emitted when the user clicks on the submit button of the "Login" screen.
- `signup submit`: emitted when the user clicks on the submit button of the "Sign up" screen.
- `federated login`: emitted when the user clicks on a social connection button. Has the connection name and the strategy as arguments.

### show(options)

Expand Down
4 changes: 3 additions & 1 deletion src/__tests__/field/social_buttons_pane.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ describe('SocialButtonsPane', () => {
signUp: false,
disabled: false
};

beforeEach(() => {
jest.resetModules();

Expand All @@ -37,7 +38,8 @@ describe('SocialButtonsPane', () => {
}));

jest.mock('core/index', () => ({
id: () => 1
id: () => 1,
emitEvent: jest.fn()
}));
});

Expand Down
10 changes: 9 additions & 1 deletion src/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,13 @@ export default class Base extends EventEmitter {
'authorization_error',
'hash_parsed',
'signin ready',
'signup ready'
'signup ready',

'forgot_password ready',
'forgot_password submit',
'signin submit',
'signup submit',
'federated login'
];

this.id = idu.incremental();
Expand Down Expand Up @@ -125,6 +131,8 @@ export default class Base extends EventEmitter {
l.emitEvent(m, 'signin ready');
} else if (screen.name === 'main.signUp') {
l.emitEvent(m, 'signup ready');
} else if (screen.name === 'forgotPassword') {
l.emitEvent(m, 'forgot_password ready');
}
}
this.oldScreenName = screen.name;
Expand Down
3 changes: 2 additions & 1 deletion src/core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ function extractAuthOptions(options) {
sso,
state,
nonce
} = options.auth || {};
} =
options.auth || {};

let { oidcConformant } = options;

Expand Down
17 changes: 17 additions & 0 deletions src/field/social/event.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import * as l from '../../core/index';

export function emitFederatedLoginEvent(lock, provider, isSignUp) {
let prov;

try {
prov = provider.toJS();
} catch (e) {
prov = provider;
}

l.emitEvent(lock, 'federated login', {
name: prov.name,
strategy: prov.strategy,
action: isSignUp ? 'signup' : 'signin'
});
}
8 changes: 7 additions & 1 deletion src/field/social/social_buttons_pane.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@ import AuthButton from '../../ui/button/auth_button';
import * as l from '../../core/index';
import { logIn } from '../../quick-auth/actions';
import { displayName, socialConnections, authButtonsTheme } from '../../connection/social/index';
import { emitFederatedLoginEvent } from './event';

export default class SocialButtonsPane extends React.Component {
handleSubmit(provider, isSignUp) {
emitFederatedLoginEvent(this.props.lock, provider, isSignUp);
return logIn(l.id(this.props.lock), provider);
}

render() {
// TODO: i don't like that it receives the instructions tanslated
// but it also takes the t fn
Expand All @@ -31,7 +37,7 @@ export default class SocialButtonsPane extends React.Component {
signUp ? 'signUpWithLabel' : 'loginWithLabel',
connectionName || displayName(x)
)}
onClick={() => logIn(l.id(lock), x)}
onClick={() => this.handleSubmit(x, signUp)}
strategy={x.get('strategy')}
primaryColor={primaryColor}
foregroundColor={foregroundColor}
Expand Down
27 changes: 26 additions & 1 deletion src/ui/box/chrome.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import ReactDOM from 'react-dom';
import ReactCSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';
import MultisizeSlide from './multisize_slide';
import GlobalMessage from './global_message';
import * as l from '../../core/index';
import Header from './header';

const submitSvg =
Expand All @@ -12,6 +13,23 @@ const submitText =
'<svg focusable="false" class="icon-text" width="8px" height="12px" viewBox="0 0 8 12" version="1.1" xmlns="http://www.w3.org/2000/svg"><g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="Web/Submit/Active" transform="translate(-148.000000, -32.000000)" fill="#FFFFFF"><polygon id="Shape" points="148 33.4 149.4 32 155.4 38 149.4 44 148 42.6 152.6 38"></polygon></g></g></svg>';

class SubmitButton extends React.Component {
handleSubmit() {
const { label, screenName, contentProps } = this.props;
const { model } = contentProps;

if (screenName === 'main.signUp') {
l.emitEvent(model, 'signup submit');
} else if (screenName === 'main.login') {
l.emitEvent(model, 'signin submit');
} else if (screenName === 'forgotPassword') {
l.emitEvent(model, 'forgot_password submit');
}

if (this.props.onSubmit) {
this.props.onSubmit(label, screenName);
}
}

focus() {
ReactDOM.findDOMNode(this).focus();
}
Expand All @@ -30,6 +48,7 @@ class SubmitButton extends React.Component {
className="auth0-lock-submit"
disabled={disabled}
style={{ backgroundColor: color }}
onClick={::this.handleSubmit}
type="submit"
>
<div className="auth0-loading-container">
Expand All @@ -44,7 +63,10 @@ class SubmitButton extends React.Component {
SubmitButton.propTypes = {
color: PropTypes.string.isRequired,
disabled: PropTypes.bool,
label: PropTypes.string
label: PropTypes.string,
screenName: PropTypes.string,
onSubmit: PropTypes.func,
contentProps: PropTypes.object
};

const MESSAGE_ANIMATION_DURATION = 250;
Expand Down Expand Up @@ -193,6 +215,8 @@ export default class Chrome extends React.Component {
<SubmitButton
color={primaryColor}
disabled={disableSubmitButton}
screenName={screenName}
contentProps={contentProps}
key="submit"
label={submitButtonLabel}
ref="submit"
Expand Down Expand Up @@ -306,6 +330,7 @@ Chrome.propTypes = {
isSubmitting: PropTypes.bool.isRequired,
logo: PropTypes.string.isRequired,
primaryColor: PropTypes.string.isRequired,
screenName: PropTypes.string.isRequired,
showSubmitButton: PropTypes.bool.isRequired,
submitButtonLabel: PropTypes.string,
success: PropTypes.node,
Expand Down
13 changes: 6 additions & 7 deletions test/social_login.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,25 @@ import expect from 'expect.js';
import Auth0Lock from '../src/index';
import * as h from './helper/ui';

describe("show lock connection scopes", function() {

describe('show lock connection scopes', function() {
beforeEach(function(done) {
h.stubWebApis();
const opts = {
auth: {
connectionScopes: {
'facebook': ['scope_1', 'scope_2']
facebook: ['scope_1', 'scope_2']
}
}
};
this.lock = h.displayLock("multiple social", opts, done);
this.lock = h.displayLock('multiple social', opts, done);
});

afterEach(function() {
this.lock.hide();
h.restoreWebApis();
});

it("should show an error flash message", function(done) {
it('should show an error flash message', function(done) {
h.assertAuthorizeRedirection((lockID, options, authParams) => {
expect(options).to.be.an('object');
expect(options.connection).to.be('facebook');
Expand All @@ -30,7 +29,7 @@ describe("show lock connection scopes", function() {
expect(options.connection_scope).to.contain('scope_1');
expect(options.connection_scope).to.contain('scope_2');
done();
})
});
h.clickSocialConnectionButton(this.lock, 'facebook');
});
});
});