Skip to content
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
44 changes: 28 additions & 16 deletions static/app/components/demo/demoHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,18 @@ import PreferencesStore from 'app/stores/preferencesStore';
import {useLegacyStore} from 'app/stores/useLegacyStore';
import space from 'app/styles/space';
import trackAdvancedAnalyticsEvent from 'app/utils/analytics/trackAdvancedAnalyticsEvent';
import {emailQueryParameter, extraQueryParameter} from 'app/utils/demoMode';
import {
extraQueryParameter,
extraQueryParameterWithEmail,
urlAttachQueryParams,
} from 'app/utils/demoMode';
import getCookie from 'app/utils/getCookie';

export default function DemoHeader() {
// if the user came from a SaaS org, we should send them back to upgrade when they leave the sandbox
const saasOrgSlug = getCookie('saas_org_slug');

const queryParameter = emailQueryParameter();
const getStartedExtraParameter = extraQueryParameter(true);
const extraParameter = extraQueryParameter(false);

const getStartedText = saasOrgSlug ? t('Upgrade Now') : t('Sign Up for Free');
const getStartedUrl = saasOrgSlug
? `https://sentry.io/settings/${saasOrgSlug}/billing/checkout/`
: `https://sentry.io/signup/${queryParameter}${getStartedExtraParameter}`;
const extraSearchParams = extraQueryParameter();

const collapsed = !!useLegacyStore(PreferencesStore).collapsed;

Expand All @@ -35,7 +32,8 @@ export default function DemoHeader() {
onClick={() =>
trackAdvancedAnalyticsEvent('growth.demo_click_docs', {organization: null})
}
href={`https://docs.sentry.io/${extraParameter}`}
href={urlAttachQueryParams('https://docs.sentry.io/', extraSearchParams)}
openInNewTab
>
{t('Documentation')}
</StyledExternalLink>
Expand All @@ -46,20 +44,34 @@ export default function DemoHeader() {
organization: null,
})
}
href={`https://sentry.io/_/demo/${extraParameter}`}
href={urlAttachQueryParams('https://sentry.io/_/demo/', extraSearchParams)}
target="_blank"
rel="noreferrer noopener"
>
{t('Request a Demo')}
</BaseButton>
<GetStarted
onClick={() =>
onClick={() => {
const url = saasOrgSlug
? `https://sentry.io/settings/${saasOrgSlug}/billing/checkout/`
: urlAttachQueryParams(
'https://sentry.io/signup/',
extraQueryParameterWithEmail()
);

// Using window.open instead of href={} because we need to read `email`
// from localStorage when the user clicks the button.
window.open(url, '_blank');
Copy link
Contributor

Choose a reason for hiding this comment

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

@Neo-Zhixing It would be nice to keep that as a link but doing that would require us to make a HoC that listens for local storage changes and re-renders the child when that happens. Maybe too much work given the level of importance. But I'd still add a comment explaining why we are calling window.open this way

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought about listening to local storage changes but that requires us to replace localStorage.setItem which is a global change. Will add lots of maintenance overhead.

https://stackoverflow.com/questions/26974084/listen-for-changes-with-localstorage-on-the-same-window

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will add comment.

Copy link
Member

Choose a reason for hiding this comment

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

You can do this with a react hook, which I think we already do in some places

Copy link
Contributor

Choose a reason for hiding this comment

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

@evanpurkhiser and which hook is that?

Copy link
Contributor

Choose a reason for hiding this comment

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

I also don't know if a hook works here when a different part of the app is updating the local storage. I think this hook only works when you're changing the session storage with the setState that the hook returns in that single component.

Copy link
Member

Choose a reason for hiding this comment

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

it would work if you have a state that is updated on localstorage change. You can use the storage event for that.

Copy link
Contributor

Choose a reason for hiding this comment

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

@evanpurkhiser

Note: This won't work on the same page that is making the changes — it is really a way for other pages on the domain using the storage to sync any changes that are made. Pages on other domains can't access the same storage objects.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

ew gross event. Yeah just do what you've got here. Or put it in reflux but 🤷


trackAdvancedAnalyticsEvent('growth.demo_click_get_started', {
is_upgrade: !!saasOrgSlug,
organization: null,
})
}
href={getStartedUrl}
});
}}
target="_blank"
rel="noreferrer noopener"
>
{getStartedText}
{saasOrgSlug ? t('Upgrade Now') : t('Sign Up for Free')}
</GetStarted>
</ButtonBar>
</Wrapper>
Expand Down
9 changes: 5 additions & 4 deletions static/app/components/modals/demoSignUp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ import HighlightModalContainer from 'app/components/highlightModalContainer';
import {t} from 'app/locale';
import space from 'app/styles/space';
import trackAdvancedAnalyticsEvent from 'app/utils/analytics/trackAdvancedAnalyticsEvent';
import {emailQueryParameter, extraQueryParameter} from 'app/utils/demoMode';
import {extraQueryParameterWithEmail, urlAttachQueryParams} from 'app/utils/demoMode';

type Props = ModalRenderProps;

const DemoSignUpModal = ({closeModal}: Props) => {
const queryParameter = emailQueryParameter();
const getStartedExtraParameter = extraQueryParameter(true);
const signupUrl = `https://sentry.io/signup/${queryParameter}${getStartedExtraParameter}`;
const signupUrl = urlAttachQueryParams(
'https://sentry.io/signup/',
extraQueryParameterWithEmail()
);

return (
<HighlightModalContainer>
Expand Down
33 changes: 17 additions & 16 deletions static/app/utils/demoMode.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import getCookie from 'app/utils/getCookie';

// return email query parameter
export function emailQueryParameter(): string {
const email = localStorage.getItem('email');
const queryParameter = email ? `?email=${email}` : '';
return queryParameter;
export function extraQueryParameter(): URLSearchParams {
// cookies that have = sign are quotes so extra quotes need to be removed
const extraQueryString = getCookie('extra_query_string')?.replaceAll('"', '') || '';
const extraQuery = new URLSearchParams(extraQueryString);
return extraQuery;
}

// return extra query depending, depending on if used in getStartedUrl
export function extraQueryParameter(getStarted: boolean): string {
export function extraQueryParameterWithEmail(): URLSearchParams {
const params = extraQueryParameter();
const email = localStorage.getItem('email');
const extraQueryString = getCookie('extra_query_string');
// cookies that have = sign are quotes so extra quotes need to be removed
const extraQuery = extraQueryString ? extraQueryString.replaceAll('"', '') : '';
if (email) {
params.append('email', email);
}
return params;
}

if (getStarted) {
const emailSeparator = email ? '&' : '?';
const getStartedSeparator = extraQueryString ? emailSeparator : '';
return getStartedSeparator + extraQuery;
export function urlAttachQueryParams(url: string, params: URLSearchParams): string {
const queryString = params.toString();
if (queryString) {
return url + '?' + queryString;
}
const extraSeparator = extraQueryString ? `?` : '';
return extraSeparator + extraQuery;
return url;
}