@bogos/freegifts-hydrogen
v0.1.0
Published
BOGOS: Free gift & Buy X Get Y - Hydrogen
Downloads
6
Readme
BOGOS: Freegifts Hydrogen App
Requirements
First, you must have Hydrogen App and BOGOS: Free gift & Buy X Get Y installed on your Shopify store.
Second, we only support development framework Hydrogen version 2 and above. You can learn how to upgrade to Hydrogen version 2 using this link.
If your Headless store was not built on Hydrogen, please refer to this API document for integration.
Installation
Step 1: Getting started
Navigate to your working directory.
cd <directory>
Install BOGOS: Free gift package
npm i @bogos/freegifts-hydrogen
Step 2: Integration
Open file containing event to render cart component (This event should be rendered on every single page), and add this basic integration:
import {BOGOS} from '@bogos/freegifts-hydrogen'; ... <Await resolve={data.cart}> {(cart) => ( <> <BOGOS cart={cart} customerAccessToken={CUSTOMER_ACCESS_TOKEN} publicStoreDomain={PUBLIC_STORE_DOMAIN} publicStorefrontApiToken={PUBLIC_STORE_FRONT_API_TOKEN} publicStorefrontApiVersion={PUBLIC_STOREFRONT_API_VERSION} bogosAccessToken={BOGOS_ACCESS_TOKEN} /> ... </> )} </Await> ...
- Details of BOGOS component properties
import { Cart, Customer } from "@shopify/hydrogen/storefront-api-types"; interface BOGOSProps { cart: Cart; customerAccessToken?: string; publicStoreDomain: string; publicStorefrontApiToken: string; publicStorefrontApiVersion: string; bogosAccessToken: string; customer?: Customer; others?: OthersSetting; renderCart?: Function; }
Find Checkout button, and add bogosCheckCartValid function to prevent gift invalid after checkout.
import {bogosCheckCartValid} from '@bogos/freegifts-hydrogen'; async function {your_function_checkout} (args) { ... await bogosCheckCartValid({}); ... }
- Details of bogosCheckCartValid function
export type BogosCheckCartValidParams = { cart?: Cart | FGObject; /* If you don't want to fetch catch again */ reloadIfInvalid?: boolean; /* Default: true. You don't want to reload page if invalid */ callback?: (isValidCart: boolean) => void; /* If you want to do something after BOGOS check */ }; export declare const bogosCheckCartValid: (params: BogosCheckCartValidParams) => Promise<boolean>;
Step 3: Details of Other settings for BOGOS
export type OthersSetting = {
isPopUp?: boolean;
customGiftImgSize?: string;
enableToastAdded?: boolean;
scaTextNotifySuccess?: string;
localesFormat?: string;
currencyCode?: string;
currencyRate?: number;
useRateForOffer?: boolean;
disableBogosAttrCart?: boolean;
disableReloadCartUpdated?: boolean;
renderCart?: Function;
useCart?: boolean;
useCustomer?: boolean;
prefixProduct?: string;
numberOrders?: number;
toFixed?: number;
debug?: boolean;
};
Step 4: Integration customize
Gift Icon
- Details of BOGOSGiftIcon
type GiftItem = { id: number; discount_type: 'percentage' | 'fixed_amount'; discount_value: number; original_price: number; // Original price - price before discount price: number; // Discount price - price after discount title: string; thumbnail?: string; }; type GiftProduct = { id: number; title: string; handle: string; thumbnail?: string; belongs_to_offer: string; variants: GiftItem[]; }; type FilterVariant = { id: string | number; title: string; price?: string | number; }; type ProductInfo = { id: string | number; handle: string; title: string; price_max?: string | number; collections?: { id: string | number; title?: string; }[]; product_type?: string; vendor?: string; variants?: FilterVariant[]; }; interface BOGOSGiftIconProps { product: ProductInfo; selectedVariant?: FilterVariant; enableForAllCondition?: boolean; /* Default false - only use with specific product condition */ page: "collection" | "product"; }; /* Example Collection page or page has list products */ <div ...> ... {products.map(product => ( <div> ... <div style={{position: 'relative'}}> ... <BOGOSGiftIcon product={{ id: product.id, handle: product.handle, title: product.title, }} page="collection" /> ... </div> ... </div> ))} ... </div> /* Example Product page */ <div ...> ... <h1 style={{width: 'fit-content', position: 'relative'}}> {title} <BOGOSGiftIcon product={{ id: product.id, handle: product.handle, title: product.title, }} page="product" /> </h1> ... </div>
- Gift-icon customization (Use it in case you want to handle the customization of gift icon instead of using BOGOS default component)
/* Other type check above */ export interface BogosCheckProductHasGiftsParams { product: ProductInfo; selectedVariant?: FilterVariant; enableForAllCondition?: boolean; } /* Return the gift product associated with purchasing the product from product page */ export declare const bogosCheckProductHasGifts: async ({ product, selectedVariant, enableForAllCondition, }: BogosCheckProductHasGiftsParams) => GiftProduct[]; export const GiftIcon = (props: Props) => { /* States */ const [gifts, setGifts] = useState<GiftProduct[]>([]); /* Vars */ const event = "fg-data:loaded"; const handleGiftIcon = async (e?: Event) => { try { setGifts(await bogosCheckProductHasGifts(props)); } catch (e) {} }; useEffect(() => { handleGiftIcon(); }, [props.selectedVariant?.id]); useEffect(() => { /* This event will run on the next render */ handleGiftIcon(); /* This event is used after fetching BOGOS' data to get information of gift icon (only run once) */ document.addEventListener(event, handleGiftIcon); return () => { document.removeEventListener(event, handleGiftIcon); }; }, []); const renderGiftIcon = useCallback(() => { const gift_icon = typeof window !== "undefined" && window?.FGSECOMAPP?.appearance?.gift_icon?.product_page?.gift_icon; /* Check if gift icon can be shown or not */ if (gifts?.length > 0 && gift_icon && gift_icon?.status) { const giftIcon = window.FGSECOMAPP?.giftIcon; // or other icon you want to show } // render gift icons }, [gifts]); return <Fragment>{renderGiftIcon()}</Fragment>; };
Gift thumbnail
- Details of BOGOSGiftThumbnail
/* Other type check above */ interface Props { product: ProductInfo; selectedVariant?: FilterVariant; enableForAllCondition?: boolean; numberGiftsThumbnail?: number; /* Default: 3. Number of gift images can be shown per thumbnail */ arrows?: boolean; dots?: boolean; prefixProduct?: string; /* Default: "/products/". Path name product */ } /* Example Product page */ <div ...> ... <BOGOSGiftThumbnail product={{ id: product.id, handle: product.handle, title: product.title, }} arrows={false} /> {{ add_to_cart_btn }} ... </div>
- Gift-thumbnail customization (Use it in case you want to handle the customization of gift thumbnail instead of using BOGOS default component)
/* Other type check above */ export interface BogosCheckProductHasGiftsParams { product: ProductInfo; selectedVariant?: FilterVariant; enableForAllCondition?: boolean; } /* Return the gift product associated with purchasing the product from product page */ export declare const bogosCheckProductHasGifts: async ({ product, selectedVariant, enableForAllCondition, }: BogosCheckProductHasGiftsParams) => GiftProduct[]; export const GiftThumbnail = (props: Props) => { /* States */ const [gifts, setGifts] = useState<GiftProduct[]>([]); /* Vars */ const event = "fg-data:loaded"; const handleGiftThumbnail = (e?: Event) => { try { const gifts = await bogosCheckProductHasGifts(props); renderGiftThumbnail(gifts); } catch (e) {} }; useEffect(() => { handleGiftThumbnail(); }, [props.selectedVariant?.id]); useEffect(() => { /* This event will run on the next render */ handleGiftThumbnail(); /* This event is used after fetching BOGOS' data to get information of gift thumbnail (only run once) */ document.addEventListener(event, handleGiftThumbnail); return () => { document.removeEventListener(event, handleGiftThumbnail); }; }, []); const renderGiftThumbnail = useCallback(() => { const gift_thumbnail = typeof window !== "undefined" && window?.FGSECOMAPP?.appearance?.gift_icon?.product_page?.gift_thumbnail; /* Check if gift thumbnail can be shown or not */ if (gifts?.length > 0 && gift_thumbnail && gift_thumbnail?.status) { } // render gift thumbnail }, [gifts]); return <Fragment>{renderGiftThumbnail()}</Fragment>; };
Cart message
- Details of BOGOSCartMessage
/* Other type check above */ interface Props { delay?: number; /* Default: 3000 (ms). Time delay between auto scroll cart message */ toFixed?: number; /* Default: 2. Number after '.' E.g: 100.00*/ } /* Example */ <div className={className}> <BOGOSCartMessage delay={5000} /> <CartEmpty ... /> <CartDetails ... /> </div>
- Cart message customization (Use it in case you want to handle the customization of cart message instead of using BOGOS default component)
/* Other type check above */ export interface BOGOSCartMessageParams { toFixed?: number; } /* return cart message can be shown */ export declare const bogosCheckCartMessage: ({ toFixed, }: BOGOSCartMessageParams) => string[]; export const CartMessage = (props: Props) => { /* States */ const [msgs, setMsgs] = useState<{value: string}[]>([]); /* Vars */ const event = "fg-cart:end-process"; const handleCartMsg = (e?: Event) => { try { const msgs = e ? (e as CustomEvent)?.detail?.data : (typeof window !== "undefined" && window?.FGSECOMAPP?.cart_message) ?? []; setMsgs(msgs); } catch (e) {} }; useEffect(() => { /* This event will run on the next render */ handleGiftCartMsg(); /* This event is used after fetching BOGOS' data to get information of cart message (only run once) */ document.addEventListener(event, handleGiftCartMsg); return () => { document.removeEventListener(event, handleGiftCartMsg); }; }, []); const renderCartMsg = useCallback(() => { const promotion_message = typeof window !== "undefined" && window?.FGSECOMAPP?.appearance?.promotion_message; /* Check if cart message can be shown or not */ if ( messages?.length > 0 && promotion_message && promotion_message?.show_on_cart_page ) { } // render gift thumbnail }, [msgs]); return <Fragment>{renderCartMsg()}</Fragment>; };
Step 5: Other integration for BOGOS: Free Gift
Hide gift product (cloned product) from your headless store
- If you use products query, you should add :
query: "tag_not:bogos-gift"
products ( ..., query: "tag_not:bogos-gift" ) { ... }
- For collection and product page, you can import bogosCheckGift and use returned value to skip gift products or replace to other pages
import {bogosCheckGift} from '@bogos/freegifts-hydrogen';
- Details of bogosCheckGift
export type ProductObject = { handle?: string; tags?: string[]; }; /* item can be product handle */ export declare const bogosCheckGift: (item: string | ProductObject) => boolean;
- If you use products query, you should add :
Customize gift popup/slider
Change isPopup to true and listen event:
type GiftItem = { id: number; discount_type: 'percentage' | 'fixed_amount'; discount_value: number; original_price: number; // Original price - price before discount price: number; // Discount price - price after discount title: string; thumbnail?: string; }; type GiftProduct = { id: number; title: string; handle: string; thumbnail?: string; belongs_to_offer: string; variants: GiftItem[]; }; export declare const bogosProcessAddGift: (variantID: number | string, quantity: number, offerId: string) => void; document.addEventListener("fg-gifts:show-slider", (e) => { console.log((e as CustomEvent).detail.arrGiftShow); /* render gift slider with arrGiftShow: GiftProduct[] */ /* use bogosProcessAddGift when click add to cart from popup to process BOGOS */ });
Details of other event listeners
- fg-gifts:updated
document.addEventListener("fg-gifts:updated", (e) => { /* use this function to re-render cart with disableReloadCartUpdated: true */ console.log((e as CustomEvent).detail); /* render gift slider with detail: { is_auto?: boolean, popup?: gift can be shown add?: gift can be added to cart update?: gift already in cart need to update } */ });
- fg-cart:auto-updated
document.addEventListener("fg-gifts:updated", (e) => { /* use this function to re-render cart with disableReloadCartUpdated: true when gifts are auto updated (add/remove) */ console.log((e as CustomEvent).detail); /* detail: { popup?: gift can be shown add?: gift can be added to cart update?: gift already in cart need to update } */ });
- fg-gifts:added: will not work if you customize gifts popup
document.addEventListener("fg-gifts:added", (e) => { /* use this function to re-render cart with disableReloadCartUpdated: true */ console.log((e as CustomEvent).detail); /* render gift slider with detail: { is_auto?: boolean, gift?: { variant_id, quantity } gift added from popup } */ });
Some features is not available on this version yet
- Stop the offer when the gift is out of stock
- Draft-Order API
Notice
Publish gift/cloned product to Headless channel (or other channels you want BOGOS package to work with)
- After creating/editing offer, please make sure that the gift/cloned product is available on Headless channel in order for the offer to work.
Support
BOGOS: Free Gift - [email protected]
OR
You can contact our live-chat supporters in app on Shopify Admin.