Skip to content

Commit

Permalink
Feature/fix issue with promotion (#83)
Browse files Browse the repository at this point in the history
* fix issues with other line items

* disable analytics

* fix analytics issues

* add another event to search

* fix cart refresh tracking
  • Loading branch information
adnansaadeddine authored Nov 4, 2024
1 parent 9c353ea commit 7b5e52b
Show file tree
Hide file tree
Showing 16 changed files with 82 additions and 33 deletions.
2 changes: 2 additions & 0 deletions components/Account/AccountOverviewContent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const shippingAddress = computed(() => customer.value.defaultShippingAddress);
const paymentMethod = computed(() => customer.value.defaultPaymentMethod);
const { latestOrder, loadLatestOrder } = useCustomerLatestOrder();
const { pushSuccess, pushError } = useNotifications();
const { trackNewsletterRegistration } = useAnalytics();
const { t } = useI18n();
const props = defineProps<{
Expand All @@ -25,6 +26,7 @@ const handleNewsletterChange = async (event: Event) => {
option: 'subscribe',
});
trackNewsletterRegistration();
pushSuccess(t('cms.element.form.newsletter.successSubscribe'));
} catch (error) {
pushError(t('cms.element.form.newsletter.errorSubscribe'));
Expand Down
2 changes: 1 addition & 1 deletion components/Checkout/CheckoutLineItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const removeCartItem = async () => {
isLoading.value = true;
try {
trackRemoveFromCart(product.value);
trackRemoveFromCart(product.value, lineItem.value.quantity);
await removeItem();
pushSuccess(t('checkout.lineItem.remove.successMessage', { lineItemName: lineItem.value.label }));
Expand Down
1 change: 1 addition & 0 deletions components/Checkout/Confirm/CheckoutConfirmPayment.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ onMounted(async () => {
description: method.translated.description,
mediaUrl: method.media?.url,
}));
trackAddPaymentInfo();
});
</script>

Expand Down
2 changes: 2 additions & 0 deletions components/Checkout/Confirm/CheckoutConfirmShipping.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ onMounted(async () => {
description: method.translated.description,
mediaUrl: method.media?.url,
}));
trackAddShippingInfo();
});
</script>

Expand Down
10 changes: 8 additions & 2 deletions components/Layout/Header/Search/LayoutHeaderSearchBar.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script setup lang="ts">
import { getProductRoute } from '@shopware-pwa/helpers-next';
import type { Schemas } from '@shopware/api-client/api-types';
const props = withDefaults(
defineProps<{
Expand All @@ -15,7 +16,7 @@ const props = withDefaults(
const emit = defineEmits(['closeSearch']);
const { searchTerm, search, getProducts, getTotal, loading } = useProductSearchSuggest();
const { trackSearchSuggestions, trackSearch } = useAnalytics();
const { trackSearchSuggestions, trackSearch, trackSelectItem } = useAnalytics();
const router = useRouter();
Expand Down Expand Up @@ -78,6 +79,11 @@ const handleEnter = () => {
}
};
const onClickProduct = (product: Schemas['Product']) => {
trackSelectItem(product, { id: 'search-suggest', name: 'search-suggest' });
emit('closeSearch')
};
onMounted(() => {
// Get the input from the ref (need querySelector since the ref returns the FormKit wrapper and not the input itself)
searchInput.value.$el.querySelector('input').focus();
Expand Down Expand Up @@ -122,7 +128,7 @@ onMounted(() => {
v-for="product in getProducts?.slice(0, displayTotal)"
:key="product.id"
:to="getProductRoute(product)"
@click="$emit('closeSearch')"
@click="onClickProduct(product)"
>
<LayoutHeaderSearchSuggestions :product="product" />
</NuxtLink>
Expand Down
3 changes: 2 additions & 1 deletion components/Product/ProductAddToCart.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ const handleEnter = async $event => {
const handleAddToCart = async () => {
try {
const quantityNumber = quantity.value ?? 1;
await addToCart();
trackAddToCart(product.value, quantity.value);
trackAddToCart(product.value, quantityNumber);
quantity.value = product.value.minPurchase;
pushSuccess(t('product.addToCart.successMessage', { productName: product.value.translated.name }));
Expand Down
1 change: 1 addition & 0 deletions composables/analytics/useAnalytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export function useAnalytics(config?: UseAnalyticsConfig): UseAnalyticsReturn {
trackSearch: analytics.trackSearch,
trackAddToWishlist: analytics.trackAddToWishlist,
trackRemoveFromWishlist: analytics.trackRemoveFromWishlist,
trackClearWishlist: analytics.trackClearWishlist,
trackLogin: analytics.trackLogin,
trackRegister: analytics.trackRegister,
trackNavigation: analytics.trackNavigation,
Expand Down
13 changes: 11 additions & 2 deletions composables/analytics/useGtag.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Schemas } from '@shopware/api-client/api-types';
import type { UseAnalyticsReturn } from '../../types/analytics/analytics';
import type { PromotionInfo } from '../../types/analytics/promotion';
import type { TrackingLineItemList } from '../tracking/useItemTracking';

export function useGtags(): UseAnalyticsReturn {
const _cookieEnabledName = 'google-analytics-enabled';
Expand All @@ -16,6 +17,7 @@ export function useGtags(): UseAnalyticsReturn {
getEventForProductList,
getEventForProduct,
getEventForProductWithPrice,
getEventForProductsWithPrice,
} = useEcommerceTrackingHelper();
const { getSearchEvent, getSearchSuggestionEvent } = useSearchTrackingHelper();
const { getPageTrackingEvent, isPageTrackingReady } = usePageTrackingHelper();
Expand Down Expand Up @@ -152,8 +154,8 @@ export function useGtags(): UseAnalyticsReturn {
_trackEvent('event', 'view_item_list', trackingEvent);
};

const trackSelectItem = (product: Schemas['Product']) => {
const trackingEvent = getEventForProduct(product);
const trackSelectItem = (product: Schemas['Product'], list?: TrackingLineItemList) => {
const trackingEvent = getEventForProduct(product, list);

_trackEvent('event', 'select_item', trackingEvent);
};
Expand Down Expand Up @@ -198,6 +200,12 @@ export function useGtags(): UseAnalyticsReturn {
_trackEvent('event', 'remove_from_wishlist', trackingEvent);
};

const trackClearWishlist = (products: Schemas['Product'][]) => {
const trackingEvent = getEventForProductsWithPrice(products);

_trackEvent('event', 'remove_from_wishlist', trackingEvent);
};

const trackLogin = () => {
_trackEvent('event', 'login');
};
Expand Down Expand Up @@ -248,6 +256,7 @@ export function useGtags(): UseAnalyticsReturn {
trackSearch,
trackAddToWishlist,
trackRemoveFromWishlist,
trackClearWishlist,
trackLogin,
trackRegister,
trackNavigation,
Expand Down
19 changes: 16 additions & 3 deletions composables/analytics/useGtm.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Schemas } from '@shopware/api-client/api-types';
import type { UseAnalyticsReturn } from '../../types/analytics/analytics';
import type { PromotionInfo } from '../../types/analytics/promotion';
import type { TrackingLineItemList } from '../tracking/useItemTracking';

export function useGtm(): UseAnalyticsReturn {
const _cookieEnabledName = 'google-analytics-enabled';
Expand All @@ -16,6 +17,7 @@ export function useGtm(): UseAnalyticsReturn {
getEventForProductList,
getEventForProduct,
getEventForProductWithPrice,
getEventForProductsWithPrice,
} = useEcommerceTrackingHelper();
const { getSearchEvent, getSearchSuggestionEvent } = useSearchTrackingHelper();
const { getPageTrackingEvent, isPageTrackingReady } = usePageTrackingHelper();
Expand Down Expand Up @@ -218,8 +220,8 @@ export function useGtm(): UseAnalyticsReturn {
});
};

const trackSelectItem = (product: Schemas['Product']) => {
const trackingEvent = getEventForProduct(product);
const trackSelectItem = (product: Schemas['Product'], list?: TrackingLineItemList) => {
const trackingEvent = getEventForProduct(product, list);

_trackEvent({ ecommerce: null });
_trackEvent({
Expand Down Expand Up @@ -256,7 +258,7 @@ export function useGtm(): UseAnalyticsReturn {
const trackSearchSuggestions = () => {
const trackingEvent = getSearchSuggestionEvent();

_trackEvent({ event: 'search_suggestions', ...trackingEvent });
_trackEvent({ event: 'search_suggest', ...trackingEvent });
};

const trackSearch = () => {
Expand Down Expand Up @@ -285,6 +287,16 @@ export function useGtm(): UseAnalyticsReturn {
});
};

const trackClearWishlist = (products: Schemas['Product'][]) => {
const trackingEvent = getEventForProductsWithPrice(products);

_trackEvent({ ecommerce: null });
_trackEvent({
event: 'remove_from_wishlist',
ecommerce: trackingEvent,
});
};

const trackLogin = () => {
_trackEvent({
event: 'login',
Expand Down Expand Up @@ -348,6 +360,7 @@ export function useGtm(): UseAnalyticsReturn {
trackSearch,
trackAddToWishlist,
trackRemoveFromWishlist,
trackClearWishlist,
trackLogin,
trackRegister,
trackNavigation,
Expand Down
5 changes: 3 additions & 2 deletions composables/tracking/page/useCartPageTracking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import type { UseAnalyticsReturn } from '../../../types/analytics/analytics';
export function useCartPageTracking(analytics: UseAnalyticsReturn) {
const cartItemsCountStore = useCartItemsStore();
const navigationStore = useNavigationStore();
const { cart } = useCart();
const { mainNavigationElements } = storeToRefs(navigationStore);
const { cartItemsCount } = storeToRefs(cartItemsCountStore);
const isCartPageReady = computed(() => !!cartItemsCount.value && !!mainNavigationElements.value.length);
const isCartPageReady = computed(() => cart.value?.lineItems.length && !!cartItemsCount.value && !!mainNavigationElements.value.length);

usePageTracking(analytics, 'cart');
whenever(isCartPageReady, () => {
setTimeout(() => analytics.trackViewCart());
analytics.trackViewCart();
}, { immediate: true });
}
25 changes: 21 additions & 4 deletions composables/tracking/useEcommerceTrackingHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ export function useEcommerceTrackingHelper() {
const getEventForAllItems = (): TrackingEcommerceEvent => {
const currentCart: Schemas['Cart'] = cart.value;
const getLineItemsTracking = currentCart.lineItems
?.map((lineItem, index) => {
?.filter(item => item.type === 'product')
.map((lineItem, index) => {
const product = _products.value.find(product => product.id === lineItem.referencedId);
if (!product) {
return;
Expand Down Expand Up @@ -88,16 +89,20 @@ export function useEcommerceTrackingHelper() {
};
};

const getEventForProduct = (product: Schemas['Product']): TrackingEcommerceEvent => {
const list = _category.value ? { id: _category.value.id, name: _category.value.name } : undefined;
const getEventForProduct = (product: Schemas['Product'], list?: TrackingLineItemList): TrackingEcommerceEvent => {
const listItem = list ?
list :
_category.value
? { id: _category.value.id, name: _category.value.name }
: undefined;
_currentProduct.value = product;

const item = getTrackingItem({
itemIndex: 1,
quantity: 1,
price: _currentProductPrice.price.value,
product,
list,
list: listItem,
});

return {
Expand All @@ -115,6 +120,17 @@ export function useEcommerceTrackingHelper() {
};
};

const getEventForProductsWithPrice = (products: Schemas['Product'][]): TrackingEcommerceEvent => {
const event = getEventForProductList(products);
const value = event.items.reduce((price, item) => price + item.price, 0);

return {
...event,
value,
currency: currencyCode.value,
};
};

const getEventWithShippingInfo = (): TrackingEcommerceEvent => {
const trackingEvent = getEventForAllItems();

Expand Down Expand Up @@ -151,6 +167,7 @@ export function useEcommerceTrackingHelper() {
getEventForProductList,
getEventForProduct,
getEventForProductWithPrice,
getEventForProductsWithPrice,
getEventWithShippingInfo,
getEventWithPaymentInfo,
getPurchasedEvent,
Expand Down
19 changes: 5 additions & 14 deletions composables/tracking/usePageTrackingHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,18 @@ export function usePageTrackingHelper() {
};

const getPageTrackingEvent = (pageType: string, sessionId?: string): TrackingPageMetaEvents => {
const event = {
return {
session_id: sessionId,
page_type: pageType,
page_path: path,
country: sessionContext.value?.shippingLocation?.country?.iso,
language: languageId.value && getLanguageCodeFromId(languageId.value),
login_status: 'logged-out',
mail: customer.value?.email,
user_id: customer.value?.id,
customer_group: customer.value?.groupId,
login_status: customer.value ? 'logged-in' : 'logged-out',
device: getDeviceType(),
};

if (customer.value) {
return {
...event,
user_id: customer.value.id,
customer_group: customer.value.groupId,
login_status: 'logged-in',
mail: customer.value.email,
};
}

return event;
};

return {
Expand Down
4 changes: 2 additions & 2 deletions nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ export default defineNuxtConfig({
shopwareEndpoint: '',
accessToken: '',
analytics: {
enabled: true,
enabled: false,
type: 'gtag',
id: 'G-XXXX',
trackingUrl: '',
trackingUrl: 'https://www.googletagmanager.com/',
}
},
},
Expand Down
4 changes: 3 additions & 1 deletion pages/wishlist.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ useBreadcrumbs([
path: '/wishlist',
},
]);
useAnalytics({ trackPageView: true, pageType: 'wishlist' });
const { trackClearWishlist } = useAnalytics({ trackPageView: true, pageType: 'wishlist' });
const products = ref<Schemas['Product'][]>([]);
Expand All @@ -32,7 +32,9 @@ const clearWishlistHandler = async () => {
isLoading.value = true;
try {
const productsList = products.value.slice(0);
await clearWishlist();
trackClearWishlist(productsList);
pushSuccess(t('wishlist.clearedSuccessfully'));
} catch (error) {
pushError(t('wishlist.errorClearingWishlist'));
Expand Down
1 change: 1 addition & 0 deletions stores/CartItemsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const useCartItemsStore = defineStore('cart-items', () => {
};

const ids = cartItems.value
.filter((item) => item.type === 'product')
.map(item => item.referencedId)
.filter((key: string | undefined): key is string => !!key);

Expand Down
4 changes: 3 additions & 1 deletion types/analytics/analytics.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Schemas } from '@shopware/api-client/api-types';
import type { TrackingLineItemList } from '../../composables/tracking/useItemTracking';
import type { PromotionInfo } from './promotion';

export type UseAnalyticsConfig = {
Expand Down Expand Up @@ -32,7 +33,7 @@ export type UseAnalyticsReturn = {
trackAddPaymentInfo: () => void;
trackPurchase: (order: Schemas['Order']) => void;
trackViewItemList: (products: Schemas['Product'][], page?: number) => void;
trackSelectItem: (product: Schemas['Product']) => void;
trackSelectItem: (product: Schemas['Product'], list?: TrackingLineItemList) => void;
trackViewItem: (product: Schemas['Product']) => void;
trackPage: (pageType: string) => void;
setUserId: (userId: string) => void;
Expand All @@ -41,6 +42,7 @@ export type UseAnalyticsReturn = {
trackSearch: () => void;
trackAddToWishlist: (product: Schemas['Product']) => void;
trackRemoveFromWishlist: (product: Schemas['Product']) => void;
trackClearWishlist: (products: Schemas['Product'][]) => void;
trackLogin: () => void;
trackRegister: () => void;
trackNavigation: (level: number, name: string) => void;
Expand Down

0 comments on commit 7b5e52b

Please sign in to comment.