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

Shopify analytics 2 #1325

Merged
merged 67 commits into from
Jun 7, 2022
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
5ac8f88
migrate shopify analytic code from old branch
wizardlyhel May 19, 2022
4e4f357
working page view
wizardlyhel May 20, 2022
549fe32
revert some entry changes
wizardlyhel May 20, 2022
7f15d0f
merge with v1.x-2022-07
wizardlyhel May 20, 2022
da764aa
clean up and put back some fix
wizardlyhel May 20, 2022
2f843ff
instrumented analytics
wizardlyhel May 20, 2022
1a09d08
fix server side analytics
wizardlyhel May 20, 2022
be26143
more page types
wizardlyhel May 20, 2022
d584497
add shopify analytics constants
wizardlyhel May 24, 2022
bb3fa18
merge with v1.x-2022-07
wizardlyhel May 24, 2022
9de0de1
move currency query to template
wizardlyhel May 24, 2022
8bb20d2
fix analytics event errors
wizardlyhel May 25, 2022
bdf1f0b
update node typescript version
wizardlyhel May 25, 2022
8314820
restore yarn lock changes
wizardlyhel May 25, 2022
f31490f
ts error
wizardlyhel May 25, 2022
29a8d15
add more fields
wizardlyhel May 25, 2022
e7864bf
match oxygen domain
wizardlyhel May 25, 2022
e68e37a
change const name so it isn't confusing
wizardlyhel May 25, 2022
5b05304
fix cookie setting
wizardlyhel May 25, 2022
5268b12
merge with v1.x-2022-07
wizardlyhel May 26, 2022
e8bb405
conditional oxygen variable
wizardlyhel May 26, 2022
eefc90f
add changeset and fix react error
wizardlyhel May 26, 2022
bd79723
fix missing import
wizardlyhel May 26, 2022
1a257ca
add shopify analytics doc
wizardlyhel May 26, 2022
8e1f80d
clean up
wizardlyhel May 26, 2022
f80f0aa
fix test
wizardlyhel May 26, 2022
c5d02c6
fix test 2
wizardlyhel May 26, 2022
82dc942
fix a bad merge
wizardlyhel May 26, 2022
da18ce1
clean up
wizardlyhel May 27, 2022
7ddeac3
add test
wizardlyhel May 27, 2022
ddd7314
remove console log
wizardlyhel May 27, 2022
3e4b46c
remove the need to specify cookie name
wizardlyhel May 30, 2022
af6e2d1
merge with v1.x-2022-07
wizardlyhel May 30, 2022
32a6d58
remove the need to use session api
wizardlyhel May 30, 2022
d65d8c2
revert session api changes
wizardlyhel May 30, 2022
12b0da5
merage with v.1x-2022-07
wizardlyhel May 30, 2022
2b8a6d2
clean up
wizardlyhel May 30, 2022
490e41d
update doc
wizardlyhel May 30, 2022
3bd1d5d
more clean up
wizardlyhel May 30, 2022
a61d87c
prettier
wizardlyhel May 30, 2022
a9ba5ec
update doc
wizardlyhel May 31, 2022
cdd13d5
update doc 2
wizardlyhel May 31, 2022
33621b5
match analytics schema
wizardlyhel May 31, 2022
d087fe5
Update .changeset/curly-phones-search.md
wizardlyhel May 31, 2022
d6105c6
Update docs/components/framework/shopifyanalytics.md
wizardlyhel May 31, 2022
87bab2e
Update docs/components/framework/shopifyanalytics.md
wizardlyhel May 31, 2022
829b27b
Update docs/components/framework/shopifyanalytics.md
wizardlyhel May 31, 2022
e37bc0b
Update docs/components/framework/shopifyanalytics.md
wizardlyhel May 31, 2022
9f56514
Update docs/components/framework/shopifyanalytics.md
wizardlyhel May 31, 2022
b966253
Update docs/components/framework/shopifyanalytics.md
wizardlyhel May 31, 2022
ad9eb06
Update docs/components/framework/shopifyanalytics.md
wizardlyhel May 31, 2022
5b9e1d3
Update docs/components/framework/shopifyanalytics.md
wizardlyhel May 31, 2022
a7f1aac
Update docs/components/framework/shopifyanalytics.md
wizardlyhel May 31, 2022
906bdd6
add work in progress disclosure
wizardlyhel May 31, 2022
476a6c1
merge
wizardlyhel May 31, 2022
7921d1d
Update docs/components/framework/shopifyanalytics.md
wizardlyhel May 31, 2022
4b02072
Update docs/components/framework/shopifyanalytics.md
wizardlyhel May 31, 2022
0674fdd
Update docs/components/framework/shopifyanalytics.md
wizardlyhel May 31, 2022
9c3b234
add related doc
wizardlyhel May 31, 2022
817de86
address feedback
wizardlyhel May 31, 2022
5ae8b85
use wrapPromise
wizardlyhel May 31, 2022
c7ea791
log error
wizardlyhel May 31, 2022
84ea431
add to cart event
wizardlyhel Jun 6, 2022
c142b58
use schema 1.2
wizardlyhel Jun 6, 2022
f6a4da4
remove the add to cart work
wizardlyhel Jun 7, 2022
c7218df
merge v1.x-20022-07
wizardlyhel Jun 7, 2022
a4d2fbc
make sure the app id is a string
wizardlyhel Jun 7, 2022
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
1 change: 1 addition & 0 deletions examples/rust/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ yarn build
```

Deploying to production will vary based on your hosting provider. Currently, Oxygen does not support Rust-based projects.

## Previewing a production build

To run a local preview of your Hydrogen app in an environment similar to Oxygen, build your Hydrogen app and then run `yarn preview`:
Expand Down
2 changes: 2 additions & 0 deletions packages/hydrogen/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
}
},
"dependencies": {
"@types/lodash-es": "^4.17.6",
"@vitejs/plugin-react": "^1.3.0",
"abort-controller": "^3.0.0",
"body-parser": "^1.20.0",
Expand All @@ -111,6 +112,7 @@
"graphql": "^16.3.0",
"history": "^5.3.0",
"kolorist": "^1.5.1",
"lodash-es": "^4.17.21",
"magic-string": "^0.26.1",
"node-fetch": "^2.6.7",
"path-to-regexp": "^6.2.0",
Expand Down
4 changes: 1 addition & 3 deletions packages/hydrogen/src/entry-server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -616,9 +616,7 @@ async function hydrate(
postRequestTasks('rsc', 200, request, componentResponse);

return new Response(bufferedBody, {
headers: {
'cache-control': componentResponse.cacheControlHeader,
},
headers: componentResponse.headers,
});
}

Expand Down
15 changes: 7 additions & 8 deletions packages/hydrogen/src/foundation/Analytics/Analytics.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,26 @@ export function Analytics({
analyticsDataFromServer: any;
}) {
useEffect(() => {
ClientAnalytics.hasSentPageView = false;
const urlParams = new URLSearchParams(window.location.search);

if (urlParams.has('utm_source')) {
ClientAnalytics.pushToPageAnalyticsData(
{
ClientAnalytics.pushToPageAnalyticsData({
utm: {
id: urlParams.get('utm_id'),
source: urlParams.get('utm_source'),
campaign: urlParams.get('utm_campaign'),
medium: urlParams.get('utm_medium'),
content: urlParams.get('utm_content'),
term: urlParams.get('utm_term'),
},
'utm'
);
});
}

ClientAnalytics.pushToPageAnalyticsData(analyticsDataFromServer);
ClientAnalytics.subscribe(ClientAnalytics.eventNames.PAGE_VIEW, () => {
ClientAnalytics.hasSentPageView = true;
});
ClientAnalytics.publish(ClientAnalytics.eventNames.PAGE_VIEW, true);
if (analyticsDataFromServer.publishEventsOnNavigate) {
analyticsDataFromServer.publishEventsOnNavigate.forEach(
Expand All @@ -32,10 +35,6 @@ export function Analytics({
}
);
}

return function cleanup() {
ClientAnalytics.resetPageAnalyticsData();
};
}, [analyticsDataFromServer]);

return null;
Expand Down
66 changes: 43 additions & 23 deletions packages/hydrogen/src/foundation/Analytics/Analytics.server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,19 @@ import {Analytics as AnalyticsClient} from './Analytics.client';
import {useServerRequest} from '../ServerRequestProvider';
import AnalyticsErrorBoundary from '../AnalyticsErrorBoundary.client';

const DELAY_KEY = 'analytics-delay';
const DELAY_KEY_1 = 'analytics-delay-1';
const DELAY_KEY_2 = 'analytics-delay-2';

export function Analytics() {
const cache = useServerRequest().ctx.cache;

// If render cache is empty, create a 50 ms delay so that React doesn't resolve this
// component too early and potentially cause a mismatch in hydration
if (cache.size === 0 && !cache.has(DELAY_KEY)) {
let result: boolean;
let promise: Promise<boolean>;

cache.set(DELAY_KEY, () => {
if (result !== undefined) {
return result;
}

if (!promise) {
promise = new Promise((resolve) => {
setTimeout(() => {
result = true;
resolve(true);
}, 50);
});
}

throw promise;
});
if (cache.size === 0 && !cache.has(DELAY_KEY_1)) {
analyticDelay(cache, DELAY_KEY_1, 50);
}
cache.has(DELAY_KEY_1) && cache.get(DELAY_KEY_1).call();
cache.delete(DELAY_KEY_1);

// Make sure all queries have returned before rendering the Analytics server component
cache.forEach((cacheFn: any) => {
Expand All @@ -41,10 +26,45 @@ export function Analytics() {
}
});

const analyticsData = useServerAnalytics();
// If all queries has returned (could be from cached queries),
// delay Analytic component by another 1ms (put this component
// to the end of the scheduled queue) so that other scheduled
// work can be processed by react first
if (cache.size > 1 && !cache.has(DELAY_KEY_2)) {
analyticDelay(cache, DELAY_KEY_2, 1);
}
cache.has(DELAY_KEY_2) && cache.get(DELAY_KEY_2).call();
cache.delete(DELAY_KEY_2);

return (
<AnalyticsErrorBoundary>
<AnalyticsClient analyticsDataFromServer={analyticsData} />
<AnalyticsClient analyticsDataFromServer={useServerAnalytics()} />
</AnalyticsErrorBoundary>
);
}

function analyticDelay(
wizardlyhel marked this conversation as resolved.
Show resolved Hide resolved
cache: Map<string, any>,
delayKey: string,
delay: number
) {
let result: boolean;
let promise: Promise<boolean>;

cache.set(delayKey, () => {
if (result !== undefined) {
return result;
}

if (!promise) {
promise = new Promise((resolve) => {
setTimeout(() => {
result = true;
resolve(true);
}, delay);
});
}

throw promise;
});
}
21 changes: 7 additions & 14 deletions packages/hydrogen/src/foundation/Analytics/ClientAnalytics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type {Subscriber, Subscribers, SubscriberFunction} from './types';
import {isServer} from '../../utilities';
import {eventNames} from './const';
import {EVENT_PATHNAME} from '../../constants';
import merge from 'lodash-es/merge';

type EventGuard = Record<string, NodeJS.Timeout>;

Expand All @@ -21,18 +22,10 @@ function isInvokedFromServer(): boolean {
return false;
}

function pushToPageAnalyticsData(data: any, namespace?: string): void {
function pushToPageAnalyticsData(data: any): void {
if (isInvokedFromServer()) return;

if (namespace) {
pageAnalyticsData[namespace] = Object.assign(
{},
pageAnalyticsData[namespace] || {},
data
);
} else {
pageAnalyticsData = Object.assign({}, pageAnalyticsData, data);
}
pageAnalyticsData = merge({}, pageAnalyticsData, data);
}

function getPageAnalyticsData(): any {
Expand All @@ -47,12 +40,11 @@ function resetPageAnalyticsData(): void {
pageAnalyticsData = {};
}

function publish(eventname: string, guardDup = false, payload?: any) {
function publish(eventname: string, guardDup = false, payload = {}) {
if (isInvokedFromServer()) return;

const namedspacedEventname = getNamedspacedEventname(eventname);
const subs = subscribers[namedspacedEventname];
const combinedPayload = Object.assign({}, pageAnalyticsData, payload);

// De-dup events due to re-renders
if (guardDup) {
Expand All @@ -63,11 +55,11 @@ function publish(eventname: string, guardDup = false, payload?: any) {
}

const namespacedTimeout = setTimeout(() => {
publishEvent(subs, combinedPayload);
publishEvent(subs, Object.assign({}, pageAnalyticsData, payload));
}, 100);
guardDupEvents[namedspacedEventname] = namespacedTimeout;
} else {
publishEvent(subs, combinedPayload);
publishEvent(subs, Object.assign({}, pageAnalyticsData, payload));
}
}

Expand Down Expand Up @@ -126,4 +118,5 @@ export const ClientAnalytics = {
subscribe,
pushToServer,
eventNames,
hasSentPageView: false,
wizardlyhel marked this conversation as resolved.
Show resolved Hide resolved
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@ export function ServerAnalyticsRoute(
request: Request,
serverAnalyticsConnectors?: Array<ServerAnalyticsConnector>
) {
if (request.headers.get('Content-Length') === '0') {
const requestHeader = request.headers;
const requestUrl = request.url;

if (requestHeader.get('Content-Length') === '0') {
serverAnalyticsConnectors?.forEach((connector) => {
connector.request(request);
connector.request(requestUrl, request.headers);
});
} else if (request.headers.get('Content-Type') === 'application/json') {
} else if (requestHeader.get('Content-Type') === 'application/json') {
Promise.resolve(request.json())
.then((data) => {
serverAnalyticsConnectors?.forEach((connector) => {
connector.request(request, data, 'json');
connector.request(requestUrl, requestHeader, data, 'json');
});
})
.catch((error) => {
Expand All @@ -23,7 +26,7 @@ export function ServerAnalyticsRoute(
Promise.resolve(request.text())
.then((data) => {
serverAnalyticsConnectors?.forEach((connector) => {
connector.request(request, data, 'text');
connector.request(requestUrl, requestHeader, data, 'text');
});
})
.catch((error) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
export function request(
request: Request,
requestUrl: string,
requestHeader: Headers,
data?: any,
contentType?: string
): void {
const url = new URL(request.url);
const url = new URL(requestUrl);
if (url.search === '?performance' && contentType === 'json') {
const initTime = new Date().getTime();

fetch('https://monorail-edge.shopifysvc.com/v1/produce', {
method: 'post',
headers: {
'content-type': 'text/plain',
'x-forwarded-for': request.headers.get('x-forwarded-for') || '',
'user-agent': request.headers.get('user-agent') || '',
'x-forwarded-for': requestHeader.get('x-forwarded-for') || '',
'user-agent': requestHeader.get('user-agent') || '',
},
body: JSON.stringify({
schema_id: 'hydrogen_buyer_performance/2.0',
Expand Down
Loading