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

chore: add new utm attributes to all mongodb links VSCODE-356 #526

Merged
merged 5 commits into from
Jun 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions src/explorer/helpTree.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as vscode from 'vscode';
import path from 'path';

import { getImagesPath } from '../extensionConstants';
import { TelemetryService } from '../telemetry';
import { openLink } from '../utils/linkHelper';
import LINKS from '../utils/links';

const HELP_LINK_CONTEXT_VALUE = 'HELP_LINK';

Expand Down Expand Up @@ -76,47 +76,49 @@ export default class HelpTree
if (!element) {
const whatsNew = new HelpLinkTreeItem(
"What's New",
'https://github.com/mongodb-js/vscode/blob/main/CHANGELOG.md',
LINKS.changelog,
'whatsNew',
'megaphone'
);

const extensionDocs = new HelpLinkTreeItem(
'Extension Documentation',
'https://docs.mongodb.com/mongodb-vscode/',
LINKS.extensionDocs(),
'extensionDocumentation',
'book'
);

const mdbDocs = new HelpLinkTreeItem(
'MongoDB Documentation',
'https://docs.mongodb.com/manual/',
LINKS.mongodbDocs,
'mongoDBDocumentation',
'leaf'
);

const feedback = new HelpLinkTreeItem(
'Suggest a Feature',
'https://feedback.mongodb.com/forums/929236-mongodb-for-vs-code/',
LINKS.feedback,
'feedback',
'lightbulb'
);

const reportBug = new HelpLinkTreeItem(
'Report a Bug',
'https://github.com/mongodb-js/vscode/issues',
LINKS.reportBug,
'reportABug',
'report'
);

const telemetryUserIdentity =
this._telemetryService?.getTelemetryUserIdentity();
const ajsAid = telemetryUserIdentity
? `&ajs_aid=${telemetryUserIdentity[0]}`
Anemy marked this conversation as resolved.
Show resolved Hide resolved
: '';

const atlas = new HelpLinkTreeItem(
'Create Free Atlas Cluster',
`https://mongodb.com/products/vs-code/vs-code-atlas-signup?utm_campaign=vs-code-extension&utm_source=visual-studio&utm_medium=product${ajsAid}`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the change, we will be missing out on utm_campaign and ajsAid query params. Just confirming if this is intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, in the ticket:

There are some links that already have UTMs, like the "Create Free Atlas Cluster" link below, they can all be standardized to be the same:

https://www.mongodb.com/products/vs-code/vs-code-atlas-signup?utm_campaign=vs-code-extension&utm_source=visual-studio&utm_medium=product&ajs_aid=undefined

can become:

https://www.mongodb.com/products/vs-code/vs-code-atlas-signup?utm_source=vscode&utm_medium=product

LINKS.createAtlasCluster(
telemetryUserIdentity?.userId ??
telemetryUserIdentity?.anonymousId ??
''
),
'freeClusterCTA',
'atlas',
true
Expand Down
7 changes: 4 additions & 3 deletions src/language/mongoDBService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import type {
import type { ClearCompletionsCache } from '../types/completionsCache';
import { Visitor } from './visitor';
import type { CompletionState } from './visitor';
import LINKS from '../utils/links';

import DIAGNOSTIC_CODES from './diagnosticCodes';

Expand Down Expand Up @@ -445,7 +446,7 @@ export default class MongoDBService {
description?: string;
}) {
const title = operator.replace(/[$]/g, '');
const link = `https://www.mongodb.com/docs/manual/reference/operator/aggregation/${title}/`;
const link = LINKS.aggregationDocs(title);
return {
kind: MarkupKind.Markdown,
value: description
Expand All @@ -461,7 +462,7 @@ export default class MongoDBService {
bsonType: string;
description?: string;
}) {
const link = `https://www.mongodb.com/docs/mongodb-shell/reference/data-types/#${bsonType}`;
const link = LINKS.bsonDocs(bsonType);
return {
kind: MarkupKind.Markdown,
value: description
Expand All @@ -478,7 +479,7 @@ export default class MongoDBService {
description?: string;
}) {
const title = variable.replace(/[$]/g, '');
const link = `https://www.mongodb.com/docs/manual/reference/aggregation-variables/#mongodb-variable-variable.${title}`;
const link = LINKS.systemVariableDocs(title);
return {
kind: MarkupKind.Markdown,
value: description
Expand Down
7 changes: 4 additions & 3 deletions src/test/suite/explorer/helpExplorer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,12 @@ suite('Help Explorer Test Suite', function () {
const atlasHelpItem = helpTreeItems[5];

assert.strictEqual(atlasHelpItem.label, 'Create Free Atlas Cluster');
const telemetryUserIdentity =
assert.strictEqual(atlasHelpItem.url.includes('mongodb.com'), true);
Anemy marked this conversation as resolved.
Show resolved Hide resolved
const { userId, anonymousId } =
mdbTestExtension.testExtensionController._telemetryService.getTelemetryUserIdentity();
assert.strictEqual(
atlasHelpItem.url,
`https://mongodb.com/products/vs-code/vs-code-atlas-signup?utm_campaign=vs-code-extension&utm_source=visual-studio&utm_medium=product&ajs_aid=${telemetryUserIdentity[0]}`
new URL(atlasHelpItem.url).searchParams.get('ajs_aid'),
userId ?? anonymousId
Anemy marked this conversation as resolved.
Show resolved Hide resolved
);
assert.strictEqual(atlasHelpItem.iconName, 'atlas');
assert.strictEqual(atlasHelpItem.linkId, 'freeClusterCTA');
Expand Down
53 changes: 53 additions & 0 deletions src/test/suite/utils/links.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { expect } from 'chai';
import LINKS from '../../../utils/links';

const expectedLinks = {
changelog: 'https://github.com/mongodb-js/vscode/blob/main/CHANGELOG.md',
feedback:
'https://feedback.mongodb.com/forums/929236-mongodb-for-vs-code/?utm_source=vscode&utm_medium=product',
github: 'https://github.com/mongodb-js/vscode',
reportBug: 'https://github.com/mongodb-js/vscode/issues',
atlas:
'https://www.mongodb.com/cloud/atlas?utm_source=vscode&utm_medium=product',
createAtlasCluster:
'https://mongodb.com/products/vs-code/vs-code-atlas-signup?ajs_aid=hi&utm_source=vscode&utm_medium=product',
docs: 'https://docs.mongodb.com/?utm_source=vscode&utm_medium=product',
mongodbDocs:
'https://docs.mongodb.com/manual/?utm_source=vscode&utm_medium=product',
extensionDocs:
'https://docs.mongodb.com/mongodb-vscode/hi?utm_source=vscode&utm_medium=product',
aggregationDocs:
'https://www.mongodb.com/docs/manual/reference/operator/aggregation/hi/?utm_source=vscode&utm_medium=product',
bsonDocs:
'https://www.mongodb.com/docs/mongodb-shell/reference/data-types/?utm_source=vscode&utm_medium=product#hi',
systemVariableDocs:
'https://www.mongodb.com/docs/manual/reference/aggregation-variables/?utm_source=vscode&utm_medium=product#mongodb-variable-variable.hi',
kerberosPrincipalDocs:
'https://docs.mongodb.com/manual/core/kerberos/?utm_source=vscode&utm_medium=product#principals',
ldapDocs:
'https://docs.mongodb.com/manual/core/security-ldap/?utm_source=vscode&utm_medium=product',
authDatabaseDocs:
'https://docs.mongodb.com/manual/core/security-users/?utm_source=vscode&utm_medium=product#user-authentication-database',
sshConnectionDocs:
'https://docs.mongodb.com/compass/current/connect/advanced-connection-options/ssh-connection/?utm_source=vscode&utm_medium=product#ssh-connection',
configureSSLDocs:
'https://docs.mongodb.com/manual/tutorial/configure-ssl/hi?utm_source=vscode&utm_medium=product',
pemKeysDocs:
'https://docs.mongodb.com/manual/reference/configuration-options/?utm_source=vscode&utm_medium=product#net.ssl.PEMKeyPassword',
};

suite('LINKS', () => {
test('should have all links', () => {
expect(Object.keys(expectedLinks)).to.deep.eq(Object.keys(LINKS));
});

Object.entries(expectedLinks).forEach(([name, expected]) => {
test(`${name} link should return ${expected}`, () => {
if (typeof LINKS[name] === 'function') {
expect(expected).to.eq(LINKS[name]('hi'));
} else {
expect(expected).to.eq(LINKS[name]);
}
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,16 @@ describe('Resources Panel Component Test Suite', () => {
'OPEN_TRUSTED_LINK'
);
assert.strictEqual(
fakeVscodeWindowPostMessage.firstCall.args[0].linkTo,
'https://mongodb.com/products/vs-code/vs-code-atlas-signup?utm_campaign=vs-code-extension&utm_source=visual-studio&utm_medium=product&ajs_aid=mockAnonymousID'
fakeVscodeWindowPostMessage.firstCall.args[0].linkTo.includes(
'mongodb.com'
),
true
);
assert.strictEqual(
new URL(
fakeVscodeWindowPostMessage.firstCall.args[0].linkTo
).searchParams.get('ajs_aid'),
'mockAnonymousID'
);
// The assert below is a bit redundant but will prevent us from redirecting to a non-https URL by mistake
assert(
Expand Down
65 changes: 65 additions & 0 deletions src/utils/links.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const addUTMAttrs = (url: string) => {
const parsed = new URL(url);
if (!parsed.host.includes('mongodb')) {
return url;
}
parsed.searchParams.set('utm_source', 'vscode');
parsed.searchParams.set('utm_medium', 'product');
return parsed.toString();
};

const LINKS = {
changelog: 'https://github.com/mongodb-js/vscode/blob/main/CHANGELOG.md',
feedback: 'https://feedback.mongodb.com/forums/929236-mongodb-for-vs-code/',
github: 'https://github.com/mongodb-js/vscode',
reportBug: 'https://github.com/mongodb-js/vscode/issues',
atlas: 'https://www.mongodb.com/cloud/atlas',
/**
* @param anonymousId Segment analytics `anonymousId` (not `userId`) {@link https://segment.com/docs/connections/sources/catalog/libraries/website/javascript/querystring/}
*/
createAtlasCluster: (anonymousId: string) => {
const ajsAid = anonymousId
? `?ajs_aid=${encodeURIComponent(anonymousId)}`
: '';
return `https://mongodb.com/products/vs-code/vs-code-atlas-signup${ajsAid}`;
},
docs: 'https://docs.mongodb.com/',
mongodbDocs: 'https://docs.mongodb.com/manual/',
extensionDocs(subcategory = '') {
return `https://docs.mongodb.com/mongodb-vscode/${subcategory}`;
},
aggregationDocs: (title: string) => {
return `https://www.mongodb.com/docs/manual/reference/operator/aggregation/${title}/`;
},
bsonDocs: (type: string) => {
return `https://www.mongodb.com/docs/mongodb-shell/reference/data-types/#${type}`;
},
systemVariableDocs: (name: string) => {
return `https://www.mongodb.com/docs/manual/reference/aggregation-variables/#mongodb-variable-variable.${name}`;
},
kerberosPrincipalDocs:
'https://docs.mongodb.com/manual/core/kerberos/#principals',
ldapDocs: 'https://docs.mongodb.com/manual/core/security-ldap/',
authDatabaseDocs:
'https://docs.mongodb.com/manual/core/security-users/#user-authentication-database',
sshConnectionDocs:
'https://docs.mongodb.com/compass/current/connect/advanced-connection-options/ssh-connection/#ssh-connection',
configureSSLDocs(subsection = '') {
return `https://docs.mongodb.com/manual/tutorial/configure-ssl/${subsection}`;
},
pemKeysDocs:
'https://docs.mongodb.com/manual/reference/configuration-options/#net.ssl.PEMKeyPassword',
};

export default Object.fromEntries(
Object.entries(LINKS).map(([k, v]) => {
return [
k,
typeof v === 'string'
? addUTMAttrs(v)
: (name: string) => {
return addUTMAttrs(v(name));
},
];
})
) as typeof LINKS;
5 changes: 3 additions & 2 deletions src/views/webview-app/components/atlas-cta/atlas-cta.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { VSCODE_EXTENSION_SEGMENT_ANONYMOUS_ID } from '../../extension-app-messa
import AtlasLogo from './atlas-logo';

import styles from './atlas-cta.less';
import LINKS from '../../../../utils/links';

type DispatchProps = {
onLinkClicked: (screen: string, linkId: string) => void;
Expand All @@ -19,7 +20,7 @@ type DispatchProps = {
class AtlasCTA extends React.Component<DispatchProps> {
onAtlasCtaClicked = (): void => {
const telemetryUserId = window[VSCODE_EXTENSION_SEGMENT_ANONYMOUS_ID];
const atlasLink = `https://mongodb.com/products/vs-code/vs-code-atlas-signup?utm_campaign=vs-code-extension&utm_source=visual-studio&utm_medium=product&ajs_aid=${telemetryUserId}`;
const atlasLink = LINKS.createAtlasCluster(telemetryUserId);
this.props.openTrustedLink(atlasLink);

this.onLinkClicked('overviewPage', 'freeClusterCTA');
Expand All @@ -43,7 +44,7 @@ class AtlasCTA extends React.Component<DispatchProps> {
className={styles['atlas-cta-text-link']}
target="_blank"
rel="noopener"
href="https://www.mongodb.com/cloud/atlas"
href={LINKS.atlas}
onClick={this.onLinkClicked.bind(
this,
'overviewPage',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import FormInput from '../../../form/form-input';

import styles from '../../../../connect.module.less';
import LINKS from '../../../../../../utils/links';

type DispatchProps = {
kerberosParametersChanged: (newParams: KerberosParameters) => void;
Expand Down Expand Up @@ -126,7 +127,7 @@ class Kerberos extends React.Component<props> {
changeHandler={this.onPrincipalChanged}
value={kerberosPrincipal || ''}
// Open the help page for the principal.
linkTo="https://docs.mongodb.com/manual/core/kerberos/#principals"
linkTo={LINKS.kerberosPrincipalDocs}
/>
<FormInput
label="Password"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
LDAPUsernameChangedAction,
} from '../../../../store/actions';
import FormInput from '../../../form/form-input';
import LINKS from '../../../../../../utils/links';

type DispatchProps = {
onLDAPPasswordChanged: (newPassword: string) => void;
Expand Down Expand Up @@ -58,7 +59,7 @@ class LDAP extends React.Component<props> {
changeHandler={this.onUsernameChanged}
value={ldapUsername || ''}
// Open the help page for LDAP.
linkTo="https://docs.mongodb.com/manual/core/security-ldap/"
linkTo={LINKS.ldapDocs}
/>
<FormInput
label="Password"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
UsernameChangedAction,
} from '../../../../store/actions';
import FormInput from '../../../form/form-input';
import LINKS from '../../../../../../utils/links';

type DispatchProps = {
onAuthSourceChanged: (newAuthSource: string) => void;
Expand Down Expand Up @@ -78,7 +79,7 @@ class MongoDBAuthentication extends React.Component<props> {
changeHandler={this.onAuthSourceChanged}
value={mongodbDatabaseName || ''}
// Opens "Authentication Database" documentation.
linkTo="https://docs.mongodb.com/manual/core/security-users/#user-authentication-database"
linkTo={LINKS.authDatabaseDocs}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
UsernameChangedAction,
} from '../../../../store/actions';
import FormInput from '../../../form/form-input';
import LINKS from '../../../../../../utils/links';

type DispatchProps = {
onAuthSourceChanged: (newAuthSource: string) => void;
Expand Down Expand Up @@ -78,7 +79,7 @@ class ScramSha256 extends React.Component<props> {
changeHandler={this.onAuthSourceChanged}
value={mongodbDatabaseName || ''}
// Opens "Authentication Database" documentation.
linkTo="https://docs.mongodb.com/manual/core/security-users/#user-authentication-database"
linkTo={LINKS.authDatabaseDocs}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { AppState } from '../../../store/store';
import FormInput from '../../form/form-input';
import FileInputButton from '../../form/file-input-button';
import FormGroup from '../../form/form-group';
import LINKS from '../../../../../utils/links';

type DispatchProps = {
onChangeSSHTunnelIdentityFile: () => void;
Expand Down Expand Up @@ -97,7 +98,7 @@ class SSHTunnelIdentityFileValidation extends React.Component<props> {
error={!isValid && sshTunnelHostname === undefined}
changeHandler={this.onSSHTunnelHostnameChanged}
value={sshTunnelHostname || ''}
linkTo="https://docs.mongodb.com/compass/current/connect"
linkTo={LINKS.sshConnectionDocs}
/>
<FormInput
label="SSH Tunnel Port"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
import { AppState } from '../../../store/store';
import FormInput from '../../form/form-input';
import FormGroup from '../../form/form-group';
import LINKS from '../../../../../utils/links';

type DispatchProps = {
onSSHTunnelHostnameChanged: (sshTunnelHostname: string) => void;
Expand Down Expand Up @@ -83,7 +84,7 @@ class SSHTunnelPasswordValidation extends React.Component<props> {
error={!isValid && sshTunnelHostname === undefined}
changeHandler={this.onSSHTunnelHostnameChanged}
value={sshTunnelHostname || ''}
linkTo="https://docs.mongodb.com/compass/current/connect"
linkTo={LINKS.sshConnectionDocs}
/>
<FormInput
label="SSH Tunnel Port"
Expand Down
Loading