[{"data":1,"prerenderedAt":1007},["ShallowReactive",2],{"header:help":3,"footer:default":67,"story:navigation\u002Fsearch:help":250,"story:help\u002Fcategories":288,"story:help\u002Farticles\u002Fadd-an-upsell-modal-to-the-checkout":314,"no-guide:add-an-upsell-modal-to-the-checkout":59,"article:\u002Fhelp\u002Farticles\u002Fadd-an-upsell-modal-to-the-checkout":743,"story:contact":764,"help:tree:368dbea3-ac85-4806-a9a3-67381c207494":952,"_apollo:default":1006},{"name":4,"created_at":5,"published_at":6,"updated_at":7,"id":8,"uuid":9,"content":10,"slug":57,"full_slug":58,"sort_by_date":59,"position":60,"tag_list":61,"is_startpage":24,"parent_id":62,"meta_data":59,"group_id":63,"first_published_at":64,"release_id":59,"lang":65,"path":59,"alternates":66,"default_full_slug":59,"translated_slugs":59},"Help Center Header","2024-08-09T18:06:34.939Z","2024-10-21T21:58:39.217Z","2024-10-21T21:58:39.232Z",10082752,"3e9b88f7-c163-4657-a2f2-62532d600fad",{"_uid":11,"link":12,"badge":16,"items":17,"title":13,"buttons":50,"new_tab":24,"submenu":51,"alignment":13,"component":52,"badge_link":53,"top_menu_items":56},"e5645a1a-f991-40e8-8d67-e40ebc082b5a",{"id":13,"url":13,"linktype":14,"fieldtype":15,"cached_url":13},"","story","multilink","Help Center",[18,27,34,39,44],{"_uid":19,"link":20,"title":23,"new_tab":24,"submenu":25,"component":26},"5cbe2861-1f49-4166-97da-a4dddd8105e3",{"id":21,"url":13,"linktype":14,"fieldtype":15,"cached_url":22},"4c0a2d99-ec30-4579-8ef1-6bf5564d4839","help\u002Fcategories\u002F","Articles",false,[],"header___item",{"_uid":28,"link":29,"title":32,"new_tab":33,"component":26},"1c8edeb5-b9e9-4cb8-b1c6-c1f292f7d7cd",{"id":13,"url":30,"linktype":31,"fieldtype":15,"cached_url":30},"https:\u002F\u002Fwiki.foxycart.com\u002F","url","Documentation",true,{"_uid":35,"link":36,"title":38,"new_tab":33,"component":26},"8d7df70e-f087-4da0-b616-6f0e9a5af35c",{"id":13,"url":37,"linktype":31,"fieldtype":15,"cached_url":37},"https:\u002F\u002Fapi.foxycart.com\u002F","API Documentation",{"_uid":40,"link":41,"title":43,"new_tab":33,"component":26},"f76e7944-23d5-4652-87e4-cdae79272762",{"id":13,"url":42,"linktype":31,"fieldtype":15,"cached_url":42},"https:\u002F\u002Fstatus.foxy.io\u002F","System Status",{"_uid":45,"link":46,"title":49,"new_tab":24,"component":26},"0de16771-4c84-466c-a1da-d8568113c71f",{"id":47,"url":13,"linktype":14,"fieldtype":15,"cached_url":48},"01e4e370-f9b9-45af-8fa9-f15540699b0d","contact","Contact Us",[],[],"header",{"id":54,"url":13,"linktype":14,"fieldtype":15,"cached_url":55},"4a679eb7-662d-4ea4-a976-5a2acbf0b663","help\u002F",[],"help-header","navigation\u002Fhelp-header",null,20,[],10082747,"71b81c2e-5e09-48a1-a397-a3c72fcd344a","2022-09-21T14:50:25.655Z","default",[],{"name":68,"created_at":69,"published_at":70,"updated_at":71,"id":72,"uuid":73,"content":74,"slug":243,"full_slug":244,"sort_by_date":59,"position":245,"tag_list":246,"is_startpage":24,"parent_id":62,"meta_data":59,"group_id":247,"first_published_at":248,"release_id":59,"lang":65,"path":59,"alternates":249,"default_full_slug":59,"translated_slugs":59},"Default Footer","2024-08-09T18:06:59.024Z","2025-09-04T06:24:46.223Z","2025-09-04T06:24:46.241Z",10082753,"e59e67ac-248a-482f-84a1-53d4f318186a",{"_uid":75,"about":76,"logos":77,"socials":82,"sections":108,"component":225,"cta_title":226,"bottom_links":227,"cta_subtitle":241,"cta_button_link":242,"cta_button_text":183},"830983f5-c4c4-43c8-b150-86a5e3fa6dc8","Foxy’s hosted cart & payment page allow you to sell anything, using your existing website or platform.",[78],{"id":79,"alt":13,"name":13,"focus":13,"title":13,"filename":80,"copyright":13,"fieldtype":81},14760,"https:\u002F\u002Fa-us.storyblok.com\u002Ff\u002F1001040\u002Fx\u002F3b030847ec\u002Fb-corp.svg","asset",[83,90,96,102],{"_uid":84,"icon":85,"link":86,"name":88,"component":89},"faf0a618-ea94-42ea-9182-03be18c43216","fa-facebook",{"id":13,"url":87,"linktype":31,"fieldtype":15,"cached_url":87},"https:\u002F\u002Fwww.facebook.com\u002Ffoxycart","Facebook","footer___social",{"_uid":91,"icon":92,"link":93,"name":95,"component":89},"14309c18-7e79-423e-b375-34555bac0811","fa-instagram",{"id":13,"url":94,"linktype":31,"fieldtype":15,"cached_url":94},"https:\u002F\u002Fwww.instagram.com\u002Ffoxy_io","Instagram",{"_uid":97,"icon":98,"link":99,"name":101,"component":89},"8f7fe7cf-0dd3-4596-8334-226ea466716a","fa-linkedin",{"id":13,"url":100,"linktype":31,"fieldtype":15,"cached_url":100},"https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Ffoxycart.com","LinkedIn",{"_uid":103,"icon":104,"link":105,"name":107,"component":89},"90a675b4-dd97-40b5-be09-00a87223d4c5","fa-youtube",{"id":13,"url":106,"linktype":31,"fieldtype":15,"cached_url":106},"https:\u002F\u002Fwww.youtube.com\u002Fuser\u002Ffoxycart","Youtube",[109,139,184,206],{"_uid":110,"name":111,"items":112,"component":138},"82849945-282f-488c-b18d-a8d2252f514a","Company",[113,120,126,132],{"_uid":114,"link":115,"title":118,"new_tab":24,"component":119},"1f699ab1-938b-4d9d-9825-aabcbe6f57fe",{"id":116,"url":13,"linktype":14,"fieldtype":15,"cached_url":117},"63634293-a749-4226-9439-9f38ee6dcda0","about-us","About Us","footer___menu_items",{"_uid":121,"link":122,"title":125,"new_tab":24,"component":119},"b26b00f1-a0e7-4be2-8ab3-428b8cc841f8",{"id":123,"url":13,"linktype":14,"fieldtype":15,"cached_url":124},"26cb7c55-faed-4a77-a291-1552d4111b3e","how-foxy-works","How Foxy Works",{"_uid":127,"link":128,"title":131,"new_tab":24,"component":119},"b40c68a0-1ceb-4226-9515-6176534f61fe",{"id":129,"url":13,"linktype":14,"fieldtype":15,"cached_url":130},"dc6657d7-7f4f-4c0d-b781-e971b038ee26","for-good","Foxy For Good",{"_uid":133,"link":134,"title":137,"new_tab":24,"component":119},"3ad0c134-bef9-4fff-b891-e09f16109036",{"id":135,"url":13,"linktype":14,"fieldtype":15,"cached_url":136},"23cae210-baf4-4588-9862-d09f4f52ccd2","brand-assets","Brand Assets","footer___section",{"_uid":140,"name":141,"items":142,"component":138},"a6805fa8-ac60-47f1-b8f0-f27aded0afbe","Product",[143,149,155,161,167,173,179],{"_uid":144,"link":145,"title":148,"new_tab":24,"component":119},"b39c8a4e-2383-486f-b76a-11fbb15d8134",{"id":146,"url":13,"linktype":14,"fieldtype":15,"cached_url":147},"bb04690f-fe98-4ce6-80be-05b950f2364f","features\u002F","Features",{"_uid":150,"link":151,"title":154,"new_tab":24,"component":119},"64f8a41f-c181-433d-bc0a-fc94e71ecbf6",{"id":152,"url":13,"linktype":14,"fieldtype":15,"cached_url":153},"c450c58d-761d-48c0-a9af-0b064611689b","pricing","Pricing",{"_uid":156,"link":157,"title":160,"new_tab":24,"component":119},"6e0b287f-fd8c-4146-9e0e-0ab0b5c9ce3c",{"id":158,"url":13,"linktype":14,"fieldtype":15,"cached_url":159},"fab20ad9-e76a-4947-b709-3a6fdfa88028","blog\u002Fcategories\u002Fproduct-updates","Product Updates",{"_uid":162,"link":163,"title":166,"new_tab":24,"component":119},"47e5a074-a6b5-4f1c-8c2f-89a2ae9f83eb",{"id":164,"url":13,"linktype":14,"fieldtype":15,"cached_url":165},"d2c83612-d611-47f3-a3b4-ca7fe08540b8","changelogs\u002F","Changelogs",{"_uid":168,"link":169,"title":172,"new_tab":24,"component":119},"b5c08774-542f-4ffd-b357-c94d674488b9",{"id":170,"url":13,"linktype":14,"fieldtype":15,"cached_url":171},"08876121-0df3-4ed9-aa11-902b3e41cd02","whats-next","What's Next",{"_uid":174,"link":175,"title":178,"new_tab":24,"component":119},"9c2704ed-6d9f-43e1-9e67-c8d91c083288",{"id":176,"url":13,"linktype":14,"fieldtype":15,"cached_url":177},"056a7857-b18f-4025-8f97-91a38fc19bc8","compare\u002F","Compare",{"_uid":180,"link":181,"title":183,"new_tab":24,"component":119},"5f2db35b-674b-406a-8fa7-d246633af9fe",{"id":13,"url":182,"linktype":31,"fieldtype":15,"cached_url":182},"https:\u002F\u002Fadmin.foxy.io\u002Fsign-up","Try Foxy Free",{"_uid":185,"name":186,"items":187,"component":138},"63fa1f29-4252-4640-9922-fe310e69e54a","Security",[188,194,200],{"_uid":189,"link":190,"title":193,"new_tab":24,"component":119},"1158ddb6-9eb0-466f-8eb6-7ca2ae66c8b8",{"id":191,"url":13,"linktype":14,"fieldtype":15,"cached_url":192},"1f58fb2c-8681-4742-b6e8-09999beae9f6","security-contact","Security Contact",{"_uid":195,"link":196,"title":199,"new_tab":24,"component":119},"9a79c54a-6022-4dfd-854b-766f5e4703ba",{"id":197,"url":13,"linktype":14,"fieldtype":15,"cached_url":198},"55cbfcc3-425a-4261-8037-54e919851d2d","pci","PCI Compliance",{"_uid":201,"link":202,"title":205,"new_tab":24,"component":119},"0b85f5b6-9534-4071-b323-b39d053dd4d7",{"id":203,"url":13,"linktype":14,"fieldtype":15,"cached_url":204},"c3ac0fe3-83e2-4879-afbd-d4c83e1590df","help\u002Farticles\u002Four-official-domains-public-code","Domains & Codebases",{"_uid":207,"name":208,"items":209,"component":138},"998ded67-d107-49f4-8154-ca6be51671ec","Support",[210,213,216,219,222],{"_uid":211,"link":212,"title":16,"new_tab":24,"component":119},"594ffd35-3049-4004-bb08-0db568ebd819",{"id":54,"url":13,"linktype":14,"fieldtype":15,"cached_url":55},{"_uid":214,"link":215,"title":32,"new_tab":33,"component":119},"0a1a55ab-a985-4f9d-8b42-26da714d0c1c",{"id":13,"url":30,"linktype":31,"fieldtype":15,"cached_url":30},{"_uid":217,"link":218,"title":38,"new_tab":33,"component":119},"61e0b7c8-aadf-419b-a339-b3ccabc65bf4",{"id":13,"url":37,"linktype":31,"fieldtype":15,"cached_url":37},{"_uid":220,"link":221,"title":43,"new_tab":33,"component":119},"fd67a89e-1c54-4d31-94b5-64be999062d6",{"id":13,"url":42,"linktype":31,"fieldtype":15,"cached_url":42},{"_uid":223,"link":224,"title":49,"new_tab":24,"component":119},"231a6f71-e996-4ad4-b033-d4d5542f34f0",{"id":47,"url":13,"linktype":14,"fieldtype":15,"cached_url":48},"footer","Get started with our *unlimited free trial*.",[228,235],{"_uid":229,"link":230,"text":233,"component":234},"f0b77210-2632-45a2-8436-e57cad84d01a",{"id":231,"url":13,"linktype":14,"fieldtype":15,"cached_url":232},"60ba16a2-c1f4-485f-b978-8d2eeeafbf5a","terms-of-service","Terms of Service","footer___bottom_links",{"_uid":236,"link":237,"text":240,"component":234},"4bd497b0-993f-4b4d-a5b7-8a49c7c8fec9",{"id":238,"url":13,"linktype":14,"fieldtype":15,"cached_url":239},"332302b9-1d18-4016-b9c8-9b33c72d782b","privacy-policy","Privacy Policy","No credit card required.",{"id":13,"url":182,"linktype":31,"fieldtype":15,"cached_url":182},"default-footer","navigation\u002Fdefault-footer",50,[],"11006268-07f9-41e9-96f3-c51fb723399d","2022-09-21T20:39:02.357Z",[],{"name":251,"created_at":252,"published_at":253,"updated_at":254,"id":255,"uuid":256,"content":257,"slug":279,"full_slug":282,"sort_by_date":59,"position":283,"tag_list":284,"is_startpage":24,"parent_id":62,"meta_data":59,"group_id":285,"first_published_at":286,"release_id":59,"lang":65,"path":59,"alternates":287,"default_full_slug":59,"translated_slugs":59},"Search","2024-10-21T22:08:54.973Z","2025-05-26T09:17:25.790Z","2025-05-26T09:17:25.804Z",13592003,"14cbc359-9ac1-4a7a-a8de-ad4ac8ef26d4",{"_uid":258,"name":251,"indices":259,"summary":13,"component":279,"primary_image":280},"5e4a56e8-76f1-4790-b3a7-70f1be97d042",[260,265,269,274],{"key":261,"_uid":262,"icon":13,"name":263,"component":264},"all","c12a3210-7323-4273-8217-5215e52efe84","All","index",{"key":266,"_uid":267,"icon":268,"name":23,"component":264},"help_center_article","5acff080-95e4-44d3-8dcf-1b19720af382","fa-file-alt",{"key":270,"_uid":271,"icon":272,"name":273,"component":264},"help_center_guide","b8fbc206-c083-471e-a1f0-0ebeb90a669d","fa-book","Guides",{"key":275,"_uid":276,"icon":277,"name":278,"component":264},"blog_post","23419e83-2e56-4c4c-8a05-9fd1b3c9a9bd","fa-file-image","Blog Posts","search",{"id":59,"alt":59,"name":13,"focus":59,"title":59,"source":59,"filename":13,"copyright":59,"fieldtype":81,"meta_data":281},{},"navigation\u002Fsearch",60,[],"11e1fd31-95cd-4fc9-b736-8b8910663e6c","2024-10-21T23:17:05.904Z",[],{"name":23,"created_at":289,"published_at":290,"updated_at":291,"id":292,"uuid":21,"content":293,"slug":307,"full_slug":22,"sort_by_date":59,"position":308,"tag_list":309,"is_startpage":33,"parent_id":310,"meta_data":59,"group_id":311,"first_published_at":312,"release_id":59,"lang":65,"path":59,"alternates":313,"default_full_slug":59,"translated_slugs":59},"2022-09-19T14:42:29.685Z","2024-07-30T18:17:22.506Z","2024-07-30T18:17:22.525Z",2660,{"_uid":294,"icon":13,"name":23,"guides":295,"pinned":24,"summary":296,"category":13,"component":297,"blog_posts":298,"content_hub":24,"icon_custom":299,"case_studies":300,"faq_sections":301,"help_articles":302,"featured_guides":303,"mailbox_category":13,"featured_articles":304,"featured_blog_posts":305,"featured_case_studies":306},"d6dae89a-907a-4bf7-82de-fe2ba875ee6e",[],"Get your questions answered with our browsable knowledge base.","help_center_category",[],{"id":59,"alt":59,"name":13,"focus":59,"title":59,"filename":13,"copyright":59,"fieldtype":81},[],[],[],[],[],[],[],"categories",530,[],2658,"19ebcdd2-027f-47f5-9a5b-a8992c959578","2022-09-19T16:24:39.219Z",[],{"name":315,"created_at":316,"published_at":317,"updated_at":318,"id":319,"uuid":320,"content":321,"slug":736,"full_slug":737,"sort_by_date":59,"position":738,"tag_list":739,"is_startpage":24,"parent_id":740,"meta_data":59,"group_id":741,"first_published_at":317,"release_id":59,"lang":65,"path":59,"alternates":742,"default_full_slug":59,"translated_slugs":59},"Add an upsell modal to the checkout","2026-07-21T17:34:12.926Z","2026-07-22T17:45:00.083Z","2026-07-22T17:45:00.105Z",200563314441131,"368dbea3-ac85-4806-a9a3-67381c207494",{"_uid":322,"body":323,"name":315,"image":731,"pinned":24,"summary":733,"category":734,"component":266,"related_articles":735},"a9e2f35a-8b09-4bee-a140-89e1cdecb5c8",{"type":324,"content":325},"doc",[326,333,346,351,358,363,388,394,418,423,428,433,438,490,496,512,517,538,543,559,581,586,591,596,625,630,635,661,666,677,688,693,698,703,708,726],{"type":327,"attrs":328,"content":329},"paragraph",{"textAlign":59},[330],{"text":331,"type":332},"Beginning in version 2.0 we've added some basic upsell functionality into the checkout. It allows you to quickly show a modal window to customers on the checkout providing opportunities for them to add additional products to their cart prior to checkout.","text",{"type":334,"content":335},"blockquote",[336],{"type":327,"attrs":337,"content":338},{"textAlign":59},[339,344],{"text":340,"type":332,"marks":341},"Tip:",[342],{"type":343},"bold",{"text":345,"type":332}," It also works on subscription cancellations! If you want to display a message before a customer cancels their subscription, this functionality can handle that as well. (Sample code at the bottom of the page.)",{"type":327,"attrs":347,"content":348},{"textAlign":59},[349],{"text":350,"type":332},"The upsell modal window is displayed on page load of the checkout, based on conditions you set within your custom Twig logic.",{"type":352,"attrs":353,"content":355},"heading",{"level":354,"textAlign":59},2,[356],{"text":357,"type":332},"Step 1: Add custom Twig to your checkout",{"type":327,"attrs":359,"content":360},{"textAlign":59},[361],{"text":362,"type":332},"To create the modal window contents, you overwrite a Twig block within your checkout template with your own HTML. When the modal functionality is enabled for your store, the actual modal window will only display to the customer if the block has some HTML elements contained within it. This means that if the block is empty, then it won't be shown to the customer. This approach is used to allow you to conditionally show the modal to the customer based on your own conditions - such as based on what products are in the cart.",{"type":327,"attrs":364,"content":365},{"textAlign":59},[366,368,374,376,380,382,386],{"text":367,"type":332},"In the Foxy admin (",{"text":369,"type":332,"marks":370},"https:\u002F\u002Fadmin.foxy.io",[371],{"type":372,"attrs":373},"link",{"href":369,"uuid":59,"anchor":59,"target":59,"linktype":31},{"text":375,"type":332},"), go to ",{"text":377,"type":332,"marks":378},"Settings > Checkout",[379],{"type":343},{"text":381,"type":332}," and edit the ",{"text":383,"type":332,"marks":384},"Custom checkout template",[385],{"type":343},{"text":387,"type":332},":",{"type":389,"attrs":390,"content":391},"code_block",{"class":59},[392],{"text":393,"type":332},"{% embed 'checkout.inc.twig' %}\n{% endembed %}",{"type":327,"attrs":395,"content":396},{"textAlign":59},[397,399,404,406,410,412,416],{"text":398,"type":332},"It is within these two lines that we'll be pasting our custom block. If you already have some other code within the ",{"text":400,"type":332,"marks":401},"embed",[402],{"type":403},"code",{"text":405,"type":332}," tags, add this additional block right before the closing ",{"text":407,"type":332,"marks":408},"{% endembed %}",[409],{"type":403},{"text":411,"type":332}," tag. Your own code will be overwriting the ",{"text":413,"type":332,"marks":414},"upsell_modal",[415],{"type":403},{"text":417,"type":332}," block - and as an initial start, will look like this:",{"type":389,"attrs":419,"content":420},{"class":59},[421],{"text":422,"type":332},"{% embed 'checkout.inc.twig' %}\n{% block upsell_modal %}\n\n{% endblock %}\n{% endembed %}",{"type":327,"attrs":424,"content":425},{"textAlign":59},[426],{"text":427,"type":332},"Inside this block tag you'll place your own custom logic and HTML. The most common use case is that of offering an link or form to add an extra product into the customers cart, unless they already have the product in their cart. That approach could look simply like this:",{"type":389,"attrs":429,"content":430},{"class":59},[431],{"text":432,"type":332},"{% block upsell_modal %}\n    {% set showUpsell = true %}\n    {% for item in items %}\n        {% if item.code == \"my-upsell\" %}\n            {% set showUpsell = false %}\n        {% endif %}\n    {% endfor %}\n    {% if showUpsell %}\n        \u003Ch2>Special offer just for you!\u003C\u002Fh2>\n        \u003Cp>As a limited time offer, we're offering you this unique product for only $12.95. That's $5 off our normal price!\u003C\u002Fp>\n        \u003Cp>\u003Ca href='https:\u002F\u002F\u002Fcart?name=Upsell+Product&code=my-upsell&price=12.95'>Yes, please add this product to my cart!\u003C\u002Fa> | \u003Ca data-remodal-action=\"cancel\">No thanks\u003C\u002Fa>\u003C\u002Fp>\n    {% endif %}\n{% endblock %}",{"type":327,"attrs":434,"content":435},{"textAlign":59},[436],{"text":437,"type":332},"A few things happens within this code.",{"type":439,"content":440},"bullet_list",[441,455,473],{"type":442,"content":443},"list_item",[444],{"type":327,"attrs":445,"content":446},{"textAlign":59},[447,449,453],{"text":448,"type":332},"Firstly, we set a variable called ",{"text":450,"type":332,"marks":451},"showUpsell",[452],{"type":403},{"text":454,"type":332}," to true",{"type":442,"content":456},[457],{"type":327,"attrs":458,"content":459},{"textAlign":59},[460,462,466,468,471],{"text":461,"type":332},"Next, we loop through the items in the cart and look for any products with a code of ",{"text":463,"type":332,"marks":464},"my-upsell",[465],{"type":403},{"text":467,"type":332},". If one is present, we set the ",{"text":450,"type":332,"marks":469},[470],{"type":403},{"text":472,"type":332}," variable to false.",{"type":442,"content":474},[475],{"type":327,"attrs":476,"content":477},{"textAlign":59},[478,480,483,485,488],{"text":479,"type":332},"Finally, if ",{"text":450,"type":332,"marks":481},[482],{"type":403},{"text":484,"type":332}," is still true, meaning the customer hasn't previously purchased the upsell - we display some HTML tempting the customer to our upsell product. If they have, and ",{"text":450,"type":332,"marks":486},[487],{"type":403},{"text":489,"type":332}," is false - we don't output any HTML, leaving the block empty and so the modal won't display at all.",{"type":352,"attrs":491,"content":493},{"level":492,"textAlign":59},3,[494],{"text":495,"type":332},"Important Notes",{"type":439,"content":497},[498,505],{"type":442,"content":499},[500],{"type":327,"attrs":501,"content":502},{"textAlign":59},[503],{"text":504,"type":332},"If your store has link and form encryption enabled, any add to carts you include within the modal will also need to be encrypted. Review the wiki page for the link\u002Fform encryption for details on doing that.",{"type":442,"content":506},[507],{"type":327,"attrs":508,"content":509},{"textAlign":59},[510],{"text":511,"type":332},"Any images that you include within your markup need to be served securely. If you're not already using a remote custom template that you're caching, you can have the image cached manually as detailed here.",{"type":352,"attrs":513,"content":514},{"level":354,"textAlign":59},[515],{"text":516,"type":332},"Step 2: Enable Upsells",{"type":327,"attrs":518,"content":519},{"textAlign":59},[520,521,525,526,530,532,536],{"text":367,"type":332},{"text":369,"type":332,"marks":522},[523],{"type":372,"attrs":524},{"href":369,"uuid":59,"anchor":59,"target":59,"linktype":31},{"text":375,"type":332},{"text":527,"type":332,"marks":528},"Settings > Templates",[529],{"type":343},{"text":531,"type":332}," and paste the following into the ",{"text":533,"type":332,"marks":534},"Custom config",[535],{"type":343},{"text":537,"type":332}," field (valid JSON only):",{"type":389,"attrs":539,"content":540},{"class":59},[541],{"text":542,"type":332},"{\n  \"upsell\": {\n    \"enabled\": true\n  }\n}",{"type":334,"content":544},[545],{"type":327,"attrs":546,"content":547},{"textAlign":59},[548,551,553,557],{"text":340,"type":332,"marks":549},[550],{"type":343},{"text":552,"type":332}," If you already have some custom JSON set in the custom value text area, you will need to merge this JSON into your own, ensuring that ",{"text":554,"type":332,"marks":555},"upsell",[556],{"type":403},{"text":558,"type":332}," is included within the first level of the JSON object.",{"type":327,"attrs":560,"content":561},{"textAlign":59},[562,564,568,570,574,576,579],{"text":563,"type":332},"If you set ",{"text":565,"type":332,"marks":566},"enabled",[567],{"type":403},{"text":569,"type":332}," to ",{"text":571,"type":332,"marks":572},"false",[573],{"type":403},{"text":575,"type":332}," in this code - it will disable the upsell functionality from operating on your cart. Alternatively you can also simply remove the above code from the ",{"text":533,"type":332,"marks":577},[578],{"type":343},{"text":580,"type":332}," field and save your configuration to turn off the upsell functionality.",{"type":352,"attrs":582,"content":583},{"level":354,"textAlign":59},[584],{"text":585,"type":332},"Step 3: Taking it further",{"type":327,"attrs":587,"content":588},{"textAlign":59},[589],{"text":590,"type":332},"You have complete control over what logic the Twig includes, and what HTML is output within the modal window. As with any Foxy templates, you can also include any custom styles you need - meaning you can create very complex and beautiful upsell displays for your store.",{"type":327,"attrs":592,"content":593},{"textAlign":59},[594],{"text":595,"type":332},"Some examples of more advanced set ups you could take:",{"type":439,"content":597},[598,605,612],{"type":442,"content":599},[600],{"type":327,"attrs":601,"content":602},{"textAlign":59},[603],{"text":604,"type":332},"Use a custom session attribute to track if a customer has already added or declined an upsell product. This could be done by sending a JSONP request off to the cart on the dismiss link being clicked, and by including the custom attribute in the add to cart. You could then check for that custom attribute in your twig logic to prevent the modal from showing again.",{"type":442,"content":606},[607],{"type":327,"attrs":608,"content":609},{"textAlign":59},[610],{"text":611,"type":332},"On page load of the checkout, you could send off a JSONP request setting a custom session attribute of the current date\u002Ftime. You could then check against that variable when deciding whether to show the upsell or not, and include a countdown timer within the modal showing how much longer the offer would be valid for.",{"type":442,"content":613},[614],{"type":327,"attrs":615,"content":616},{"textAlign":59},[617,619,623],{"text":618,"type":332},"If you wanted to also trigger the upsell modal off of other events on the checkout - such as removing a product from their cart or clicking a button or link - it can be shown by calling ",{"text":620,"type":332,"marks":621},"FC.checkout.showUpsellModal()",[622],{"type":403},{"text":624,"type":332},". This function will re-render the upsell block and display if it's enabled and has at least one HTML element within the block to display.",{"type":352,"attrs":626,"content":627},{"level":492,"textAlign":59},[628],{"text":629,"type":332},"Only showing the upsell window once across customer sessions",{"type":327,"attrs":631,"content":632},{"textAlign":59},[633],{"text":634,"type":332},"If you want to ensure the customer only sees the upsell modal once across multiple different checkout attempts, you can utilise cookies to store details about the customer that can be retrieved in future checkout sessions. As an example, the following code will add a cookie that will last for 30 days if the customer either closes the upsell modal or submits the add to cart form, preventing the customer from seeing it again for that timeframe.",{"type":327,"attrs":636,"content":637},{"textAlign":59},[638,639,643,644,647,649,653,655,659],{"text":367,"type":332},{"text":369,"type":332,"marks":640},[641],{"type":372,"attrs":642},{"href":369,"uuid":59,"anchor":59,"target":59,"linktype":31},{"text":375,"type":332},{"text":527,"type":332,"marks":645},[646],{"type":343},{"text":648,"type":332}," and add the code to the ",{"text":650,"type":332,"marks":651},"Custom footer",[652],{"type":343},{"text":654,"type":332}," field (Twig is supported; it is injected before the closing ",{"text":656,"type":332,"marks":657},"\u003C\u002Fbody>",[658],{"type":403},{"text":660,"type":332}," tag):",{"type":389,"attrs":662,"content":663},{"class":59},[664],{"text":665,"type":332},"{% if context == \"checkout\" %}\n\u003Cscript>\n    var upsell_cookie_name = \"fc_completed_upsell\",\n        cookie_expires_in = 30; \u002F\u002F default, in days\n \n    $(function() {\n        var has_upsell_cookie = document.cookie.split(';').filter(function(item) {\n                return item.indexOf(upsell_cookie_name + '=') >= 0\n            }).length;\n        if (has_upsell_cookie) {\n            $('[data-fc-id=\"block-upsell-modal\"]').html(\"\");\n            if (FC.checkout.upsell_modal) {\n                FC.checkout.upsell_modal.close();\n            }\n        }\n \n        \u002F\u002F On closing the modal\n        $('body').on(\"mousedown\", '[data-fc-id=\"block-upsell-modal\"] [data-remodal-action=\"cancel\"]', function() { addUpsellCookie(); });\n        \u002F\u002F On submitting a form in the modal\n        $('body').on(\"submit\", '[data-fc-id=\"block-upsell-modal\"] form', function() { addUpsellCookie(); });\n    });\n \n    function addUpsellCookie(days) {\n        var expires = \"\",\n            date = new Date(),\n            days = parseInt(days);\n        \n        if (typeof days !== \"number\" || !isFinite(days) || Math.floor(days) !== days) {\n            days = cookie_expires_in;\n        }\n\n        date.setTime(date.getTime() + (days*24*60*60*1000));\n        expires = \"; expires=\" + date.toUTCString();\n        document.cookie = upsell_cookie_name + \"=true\" + expires + \"; path=\u002F\";\n    }\n\u003C\u002Fscript>\n{% endif %}",{"type":327,"attrs":667,"content":668},{"textAlign":59},[669,671,675],{"text":670,"type":332},"You can modify this script as needed, updating the ",{"text":672,"type":332,"marks":673},"cookie_expires_in",[674],{"type":403},{"text":676,"type":332}," variable to change the number of days they shouldn't see the upsell for.",{"type":327,"attrs":678,"content":679},{"textAlign":59},[680,682,686],{"text":681,"type":332},"The script also supports passing a custom cookie length, in days, to the ",{"text":683,"type":332,"marks":684},"addUpsellCookie()",[685],{"type":403},{"text":687,"type":332}," function, so you could customise the number of days the customer shouldn't see the upsell modal for depending on what they interact with. If no parameter is passed, then the default value is used from the top of the script (30 days in the example code above). For example, if you wanted to just hide the modal if cancelled for the default amount, but hide for a year if the customer submits the form - you could edit the form submission event hook like this:",{"type":389,"attrs":689,"content":690},{"class":59},[691],{"text":692,"type":332},"$('body').on(\"submit\", '[data-fc-id=\"block-upsell-modal\"] form', function() { addUpsellCookie(365); });",{"type":327,"attrs":694,"content":695},{"textAlign":59},[696],{"text":697,"type":332},"Finally, you can also comment out either of the event hooks that are triggered on closing the modal or submitting a form, depending on your needs. For example if you only wanted to prevent the upsell from showing again if the customer submits the form, you would comment out this line like this:",{"type":389,"attrs":699,"content":700},{"class":59},[701],{"text":702,"type":332},"\u002F\u002F $('body').on(\"mousedown\", '[data-fc-id=\"block-upsell-modal\"] [data-remodal-action=\"cancel\"]', function() { addUpsellCookie(); });",{"type":352,"attrs":704,"content":705},{"level":354,"textAlign":59},[706],{"text":707,"type":332},"Displaying a Subscription Cancellation Upsell or Message",{"type":327,"attrs":709,"content":710},{"textAlign":59},[711,713,717,719,724],{"text":712,"type":332},"All the steps above should be followed, but here's code tailored to display the message based on the ",{"text":714,"type":332,"marks":715},"is_subscription_cancel",[716],{"type":403},{"text":718,"type":332}," value. This will ",{"text":720,"type":332,"marks":721},"only",[722],{"type":723},"italic",{"text":725,"type":332}," display when a customer uses a subscription cancellation link:",{"type":389,"attrs":727,"content":728},{"class":59},[729],{"text":730,"type":332},"{% block upsell_modal %}\n    {% if is_subscription_cancel %}\n    \u003Cdiv id=\"cancelConfirmModal\">\n        \u003Ch2>Hi there! Before You Cancel...\u003C\u002Fh2>\n        \u003Cp>We understand things change, but if you're cancelling because:\u003C\u002Fp>\n        \u003Cul>\n            \u003Cli>You're not getting the value you expected?\u003C\u002Fli>\n            \u003Cli>Encountering technical difficulties?\u003C\u002Fli>\n            \u003Cli>Finding it complex to use?\u003C\u002Fli>\n            \u003Cli>Have questions about your plan or billing?\u003C\u002Fli>\n        \u003C\u002Ful>\n        \u003Cp>We're here to help you get the most out of our service! And we're happy to help.\u003C\u002Fp>\n        \u003Cdiv>\n            \u003Cul>\n            \u003Cli>\n                \u003Ca href=\"mailto:hello@example.com\">✉️ Email Support or Schedule a Call\u003C\u002Fa>\n            \u003C\u002Fli>\n            \u003Cli>\n                \u003Ca data-remodal-action=\"cancel\">No Thanks, Continue to Cancel…\u003C\u002Fa>\n            \u003C\u002Fli>\n            \u003C\u002Ful>\n        \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n    {% endif %}\n{% endblock %}",{"id":59,"alt":59,"name":13,"focus":59,"title":59,"source":59,"filename":13,"copyright":59,"fieldtype":81,"meta_data":732},{},"How to show a modal at checkout that lets customers quickly add more products before completing their order.","c86d4c1b-9299-4716-802e-52f91ac178b0",[],"add-an-upsell-modal-to-the-checkout","help\u002Farticles\u002Fadd-an-upsell-modal-to-the-checkout",-4240,[],2659,"93299017-a7c7-44f6-bfa3-e63b67fe1bf8",[],{"html":744,"sections":745,"segments":760},"\u003Cp>Beginning in version 2.0 we&#039;ve added some basic upsell functionality into the checkout. It allows you to quickly show a modal window to customers on the checkout providing opportunities for them to add additional products to their cart prior to checkout.\u003C\u002Fp>\u003Cblockquote>\u003Cp>\u003Cstrong>Tip:\u003C\u002Fstrong> It also works on subscription cancellations! If you want to display a message before a customer cancels their subscription, this functionality can handle that as well. (Sample code at the bottom of the page.)\u003C\u002Fp>\u003C\u002Fblockquote>\u003Cp>The upsell modal window is displayed on page load of the checkout, based on conditions you set within your custom Twig logic.\u003C\u002Fp>\u003Csection id=\"step-1-add-custom-twig-to-your-checkout\" data-title=\"Step 1: Add custom Twig to your checkout\" data-title-node=\"H2\">\u003Chr class=\"my-8\" style=\"margin-left: -48px; margin-right: -40vw\">\u003Ch2 data-anchor-id=\"step-1-add-custom-twig-to-your-checkout\">Step 1: Add custom Twig to your checkout\u003C\u002Fh2>\u003Cp>To create the modal window contents, you overwrite a Twig block within your checkout template with your own HTML. When the modal functionality is enabled for your store, the actual modal window will only display to the customer if the block has some HTML elements contained within it. This means that if the block is empty, then it won&#039;t be shown to the customer. This approach is used to allow you to conditionally show the modal to the customer based on your own conditions - such as based on what products are in the cart.\u003C\u002Fp>\u003Cp>In the Foxy admin (\u003Ca href=\"https:\u002F\u002Fadmin.foxy.io\" class=\"\">https:\u002F\u002Fadmin.foxy.io\u003C\u002Fa>), go to \u003Cstrong>Settings &gt; Checkout\u003C\u002Fstrong> and edit the \u003Cstrong>Custom checkout template\u003C\u002Fstrong>:\u003C\u002Fp>\u003Cdiv class=\"position-relative w-100 overflow-hidden rounded-2\" data-code-block>\u003Cdiv class=\"d-flex justify-content-end border-bottom\" style=\"background:#2b2c3b;\">\u003Cbutton type=\"button\" class=\"btn btn-link btn-sm text-light\" title=\"Copy\" data-code-button>\u003Cspan data-code-default style=\"\">\u003Ci class=\"fal fa-copy me-2\">\u003C\u002Fi> Copy \u003C\u002Fspan>\u003Cspan class=\"text-success\" data-code-success style=\"display:none;\">\u003Ci class=\"fal fa-check ms-2\">\u003C\u002Fi> Copied \u003C\u002Fspan>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003Cdiv class=\"small\">\u003Cpre class=\"hljs p-2\" data-code-content>{% embed &#x27;checkout.inc.twig&#x27; %}\n{% endembed %}\u003C\u002Fpre>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cp>It is within these two lines that we&#039;ll be pasting our custom block. If you already have some other code within the \u003Ccode class=\"badge bg-soft-danger text-danger\">embed\u003C\u002Fcode> tags, add this additional block right before the closing \u003Ccode class=\"badge bg-soft-danger text-danger\">{% endembed %}\u003C\u002Fcode> tag. Your own code will be overwriting the \u003Ccode class=\"badge bg-soft-danger text-danger\">upsell_modal\u003C\u002Fcode> block - and as an initial start, will look like this:\u003C\u002Fp>\u003Cdiv class=\"position-relative w-100 overflow-hidden rounded-2\" data-code-block>\u003Cdiv class=\"d-flex justify-content-end border-bottom\" style=\"background:#2b2c3b;\">\u003Cbutton type=\"button\" class=\"btn btn-link btn-sm text-light\" title=\"Copy\" data-code-button>\u003Cspan data-code-default style=\"\">\u003Ci class=\"fal fa-copy me-2\">\u003C\u002Fi> Copy \u003C\u002Fspan>\u003Cspan class=\"text-success\" data-code-success style=\"display:none;\">\u003Ci class=\"fal fa-check ms-2\">\u003C\u002Fi> Copied \u003C\u002Fspan>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003Cdiv class=\"small\">\u003Cpre class=\"hljs p-2\" data-code-content>{% embed &#x27;checkout.inc.twig&#x27; %}\n{% block upsell_modal %}\n\n{% endblock %}\n{% endembed %}\u003C\u002Fpre>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cp>Inside this block tag you&#039;ll place your own custom logic and HTML. The most common use case is that of offering an link or form to add an extra product into the customers cart, unless they already have the product in their cart. That approach could look simply like this:\u003C\u002Fp>\u003Cdiv class=\"position-relative w-100 overflow-hidden rounded-2\" data-code-block>\u003Cdiv class=\"d-flex justify-content-end border-bottom\" style=\"background:#2b2c3b;\">\u003Cbutton type=\"button\" class=\"btn btn-link btn-sm text-light\" title=\"Copy\" data-code-button>\u003Cspan data-code-default style=\"\">\u003Ci class=\"fal fa-copy me-2\">\u003C\u002Fi> Copy \u003C\u002Fspan>\u003Cspan class=\"text-success\" data-code-success style=\"display:none;\">\u003Ci class=\"fal fa-check ms-2\">\u003C\u002Fi> Copied \u003C\u002Fspan>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003Cdiv class=\"small\">\u003Cpre class=\"hljs p-2\" data-code-content>{% block upsell_modal %}\n    {% set showUpsell = true %}\n    {% for item in items %}\n        {% if item.code == &quot;my-upsell&quot; %}\n            {% set showUpsell = false %}\n        {% endif %}\n    {% endfor %}\n    {% if showUpsell %}\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">h2\u003C\u002Fspan>&gt;\u003C\u002Fspan>Special offer just for you!\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">h2\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>As a limited time offer, we&#x27;re offering you this unique product for only $12.95. That&#x27;s $5 off our normal price!\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">a\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">href\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&#x27;https:\u002F\u002F\u002Fcart?name=Upsell+Product&amp;code=my-upsell&amp;price=12.95&#x27;\u003C\u002Fspan>&gt;\u003C\u002Fspan>Yes, please add this product to my cart!\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">a\u003C\u002Fspan>&gt;\u003C\u002Fspan> | \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">a\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">data-remodal-action\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;cancel&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>No thanks\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">a\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n    {% endif %}\n{% endblock %}\u003C\u002Fpre>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cp>A few things happens within this code.\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cp>Firstly, we set a variable called \u003Ccode class=\"badge bg-soft-danger text-danger\">showUpsell\u003C\u002Fcode> to true\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>Next, we loop through the items in the cart and look for any products with a code of \u003Ccode class=\"badge bg-soft-danger text-danger\">my-upsell\u003C\u002Fcode>. If one is present, we set the \u003Ccode class=\"badge bg-soft-danger text-danger\">showUpsell\u003C\u002Fcode> variable to false.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>Finally, if \u003Ccode class=\"badge bg-soft-danger text-danger\">showUpsell\u003C\u002Fcode> is still true, meaning the customer hasn&#039;t previously purchased the upsell - we display some HTML tempting the customer to our upsell product. If they have, and \u003Ccode class=\"badge bg-soft-danger text-danger\">showUpsell\u003C\u002Fcode> is false - we don&#039;t output any HTML, leaving the block empty and so the modal won&#039;t display at all.\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fsection>\u003Csection id=\"important-notes\" data-title=\"Important Notes\" data-title-node=\"H3\">\u003Ch3 data-anchor-id=\"important-notes\">Important Notes\u003C\u002Fh3>\u003Cul>\u003Cli>\u003Cp>If your store has link and form encryption enabled, any add to carts you include within the modal will also need to be encrypted. Review the wiki page for the link\u002Fform encryption for details on doing that.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>Any images that you include within your markup need to be served securely. If you&#039;re not already using a remote custom template that you&#039;re caching, you can have the image cached manually as detailed here.\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fsection>\u003Csection id=\"step-2-enable-upsells\" data-title=\"Step 2: Enable Upsells\" data-title-node=\"H2\">\u003Chr class=\"my-8\" style=\"margin-left: -48px; margin-right: -40vw\">\u003Ch2 data-anchor-id=\"step-2-enable-upsells\">Step 2: Enable Upsells\u003C\u002Fh2>\u003Cp>In the Foxy admin (\u003Ca href=\"https:\u002F\u002Fadmin.foxy.io\" class=\"\">https:\u002F\u002Fadmin.foxy.io\u003C\u002Fa>), go to \u003Cstrong>Settings &gt; Templates\u003C\u002Fstrong> and paste the following into the \u003Cstrong>Custom config\u003C\u002Fstrong> field (valid JSON only):\u003C\u002Fp>\u003Cdiv class=\"position-relative w-100 overflow-hidden rounded-2\" data-code-block>\u003Cdiv class=\"d-flex justify-content-end border-bottom\" style=\"background:#2b2c3b;\">\u003Cbutton type=\"button\" class=\"btn btn-link btn-sm text-light\" title=\"Copy\" data-code-button>\u003Cspan data-code-default style=\"\">\u003Ci class=\"fal fa-copy me-2\">\u003C\u002Fi> Copy \u003C\u002Fspan>\u003Cspan class=\"text-success\" data-code-success style=\"display:none;\">\u003Ci class=\"fal fa-check ms-2\">\u003C\u002Fi> Copied \u003C\u002Fspan>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003Cdiv class=\"small\">\u003Cpre class=\"hljs p-2\" data-code-content>{\n  &quot;upsell&quot;: {\n    &quot;enabled&quot;: true\n  }\n}\u003C\u002Fpre>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cblockquote>\u003Cp>\u003Cstrong>Tip:\u003C\u002Fstrong> If you already have some custom JSON set in the custom value text area, you will need to merge this JSON into your own, ensuring that \u003Ccode class=\"badge bg-soft-danger text-danger\">upsell\u003C\u002Fcode> is included within the first level of the JSON object.\u003C\u002Fp>\u003C\u002Fblockquote>\u003Cp>If you set \u003Ccode class=\"badge bg-soft-danger text-danger\">enabled\u003C\u002Fcode> to \u003Ccode class=\"badge bg-soft-danger text-danger\">false\u003C\u002Fcode> in this code - it will disable the upsell functionality from operating on your cart. Alternatively you can also simply remove the above code from the \u003Cstrong>Custom config\u003C\u002Fstrong> field and save your configuration to turn off the upsell functionality.\u003C\u002Fp>\u003C\u002Fsection>\u003Csection id=\"step-3-taking-it-further\" data-title=\"Step 3: Taking it further\" data-title-node=\"H2\">\u003Chr class=\"my-8\" style=\"margin-left: -48px; margin-right: -40vw\">\u003Ch2 data-anchor-id=\"step-3-taking-it-further\">Step 3: Taking it further\u003C\u002Fh2>\u003Cp>You have complete control over what logic the Twig includes, and what HTML is output within the modal window. As with any Foxy templates, you can also include any custom styles you need - meaning you can create very complex and beautiful upsell displays for your store.\u003C\u002Fp>\u003Cp>Some examples of more advanced set ups you could take:\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cp>Use a custom session attribute to track if a customer has already added or declined an upsell product. This could be done by sending a JSONP request off to the cart on the dismiss link being clicked, and by including the custom attribute in the add to cart. You could then check for that custom attribute in your twig logic to prevent the modal from showing again.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>On page load of the checkout, you could send off a JSONP request setting a custom session attribute of the current date\u002Ftime. You could then check against that variable when deciding whether to show the upsell or not, and include a countdown timer within the modal showing how much longer the offer would be valid for.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>If you wanted to also trigger the upsell modal off of other events on the checkout - such as removing a product from their cart or clicking a button or link - it can be shown by calling \u003Ccode class=\"badge bg-soft-danger text-danger\">FC.checkout.showUpsellModal()\u003C\u002Fcode>. This function will re-render the upsell block and display if it&#039;s enabled and has at least one HTML element within the block to display.\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fsection>\u003Csection id=\"only-showing-the-upsell-window-once-across-customer-sessions\" data-title=\"Only showing the upsell window once across customer sessions\" data-title-node=\"H3\">\u003Ch3 data-anchor-id=\"only-showing-the-upsell-window-once-across-customer-sessions\">Only showing the upsell window once across customer sessions\u003C\u002Fh3>\u003Cp>If you want to ensure the customer only sees the upsell modal once across multiple different checkout attempts, you can utilise cookies to store details about the customer that can be retrieved in future checkout sessions. As an example, the following code will add a cookie that will last for 30 days if the customer either closes the upsell modal or submits the add to cart form, preventing the customer from seeing it again for that timeframe.\u003C\u002Fp>\u003Cp>In the Foxy admin (\u003Ca href=\"https:\u002F\u002Fadmin.foxy.io\" class=\"\">https:\u002F\u002Fadmin.foxy.io\u003C\u002Fa>), go to \u003Cstrong>Settings &gt; Templates\u003C\u002Fstrong> and add the code to the \u003Cstrong>Custom footer\u003C\u002Fstrong> field (Twig is supported; it is injected before the closing \u003Ccode class=\"badge bg-soft-danger text-danger\">&lt;\u002Fbody&gt;\u003C\u002Fcode> tag):\u003C\u002Fp>\u003Cdiv class=\"position-relative w-100 overflow-hidden rounded-2\" data-code-block>\u003Cdiv class=\"d-flex justify-content-end border-bottom\" style=\"background:#2b2c3b;\">\u003Cbutton type=\"button\" class=\"btn btn-link btn-sm text-light\" title=\"Copy\" data-code-button>\u003Cspan data-code-default style=\"\">\u003Ci class=\"fal fa-copy me-2\">\u003C\u002Fi> Copy \u003C\u002Fspan>\u003Cspan class=\"text-success\" data-code-success style=\"display:none;\">\u003Ci class=\"fal fa-check ms-2\">\u003C\u002Fi> Copied \u003C\u002Fspan>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003Cdiv class=\"small\">\u003Cpre class=\"hljs p-2\" data-code-content>{% if context == &quot;checkout&quot; %}\n\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">script\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"language-javascript\">\n    \u003Cspan class=\"hljs-keyword\">var\u003C\u002Fspan> upsell_cookie_name = \u003Cspan class=\"hljs-string\">&quot;fc_completed_upsell&quot;\u003C\u002Fspan>,\n        cookie_expires_in = \u003Cspan class=\"hljs-number\">30\u003C\u002Fspan>; \u003Cspan class=\"hljs-comment\">\u002F\u002F default, in days\u003C\u002Fspan>\n \n    $(\u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) {\n        \u003Cspan class=\"hljs-keyword\">var\u003C\u002Fspan> has_upsell_cookie = \u003Cspan class=\"hljs-variable language_\">document\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">cookie\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">split\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;;&#x27;\u003C\u002Fspan>).\u003Cspan class=\"hljs-title function_\">filter\u003C\u002Fspan>(\u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">item\u003C\u002Fspan>) {\n                \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> item.\u003Cspan class=\"hljs-title function_\">indexOf\u003C\u002Fspan>(upsell_cookie_name + \u003Cspan class=\"hljs-string\">&#x27;=&#x27;\u003C\u002Fspan>) &gt;= \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>\n            }).\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan>;\n        \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (has_upsell_cookie) {\n            $(\u003Cspan class=\"hljs-string\">&#x27;[data-fc-id=&quot;block-upsell-modal&quot;]&#x27;\u003C\u002Fspan>).\u003Cspan class=\"hljs-title function_\">html\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&quot;&quot;\u003C\u002Fspan>);\n            \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"hljs-variable constant_\">FC\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">checkout\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">upsell_modal\u003C\u002Fspan>) {\n                \u003Cspan class=\"hljs-variable constant_\">FC\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">checkout\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">upsell_modal\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">close\u003C\u002Fspan>();\n            }\n        }\n \n        \u003Cspan class=\"hljs-comment\">\u002F\u002F On closing the modal\u003C\u002Fspan>\n        $(\u003Cspan class=\"hljs-string\">&#x27;body&#x27;\u003C\u002Fspan>).\u003Cspan class=\"hljs-title function_\">on\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&quot;mousedown&quot;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;[data-fc-id=&quot;block-upsell-modal&quot;] [data-remodal-action=&quot;cancel&quot;]&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) { \u003Cspan class=\"hljs-title function_\">addUpsellCookie\u003C\u002Fspan>(); });\n        \u003Cspan class=\"hljs-comment\">\u002F\u002F On submitting a form in the modal\u003C\u002Fspan>\n        $(\u003Cspan class=\"hljs-string\">&#x27;body&#x27;\u003C\u002Fspan>).\u003Cspan class=\"hljs-title function_\">on\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&quot;submit&quot;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;[data-fc-id=&quot;block-upsell-modal&quot;] form&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) { \u003Cspan class=\"hljs-title function_\">addUpsellCookie\u003C\u002Fspan>(); });\n    });\n \n    \u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">addUpsellCookie\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">days\u003C\u002Fspan>) {\n        \u003Cspan class=\"hljs-keyword\">var\u003C\u002Fspan> expires = \u003Cspan class=\"hljs-string\">&quot;&quot;\u003C\u002Fspan>,\n            date = \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Date\u003C\u002Fspan>(),\n            days = \u003Cspan class=\"hljs-built_in\">parseInt\u003C\u002Fspan>(days);\n        \n        \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"hljs-keyword\">typeof\u003C\u002Fspan> days !== \u003Cspan class=\"hljs-string\">&quot;number&quot;\u003C\u002Fspan> || !\u003Cspan class=\"hljs-built_in\">isFinite\u003C\u002Fspan>(days) || \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">floor\u003C\u002Fspan>(days) !== days) {\n            days = cookie_expires_in;\n        }\n\n        date.\u003Cspan class=\"hljs-title function_\">setTime\u003C\u002Fspan>(date.\u003Cspan class=\"hljs-title function_\">getTime\u003C\u002Fspan>() + (days*\u003Cspan class=\"hljs-number\">24\u003C\u002Fspan>*\u003Cspan class=\"hljs-number\">60\u003C\u002Fspan>*\u003Cspan class=\"hljs-number\">60\u003C\u002Fspan>*\u003Cspan class=\"hljs-number\">1000\u003C\u002Fspan>));\n        expires = \u003Cspan class=\"hljs-string\">&quot;; expires=&quot;\u003C\u002Fspan> + date.\u003Cspan class=\"hljs-title function_\">toUTCString\u003C\u002Fspan>();\n        \u003Cspan class=\"hljs-variable language_\">document\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">cookie\u003C\u002Fspan> = upsell_cookie_name + \u003Cspan class=\"hljs-string\">&quot;=true&quot;\u003C\u002Fspan> + expires + \u003Cspan class=\"hljs-string\">&quot;; path=\u002F&quot;\u003C\u002Fspan>;\n    }\n\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">script\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n{% endif %}\u003C\u002Fpre>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cp>You can modify this script as needed, updating the \u003Ccode class=\"badge bg-soft-danger text-danger\">cookie_expires_in\u003C\u002Fcode> variable to change the number of days they shouldn&#039;t see the upsell for.\u003C\u002Fp>\u003Cp>The script also supports passing a custom cookie length, in days, to the \u003Ccode class=\"badge bg-soft-danger text-danger\">addUpsellCookie()\u003C\u002Fcode> function, so you could customise the number of days the customer shouldn&#039;t see the upsell modal for depending on what they interact with. If no parameter is passed, then the default value is used from the top of the script (30 days in the example code above). For example, if you wanted to just hide the modal if cancelled for the default amount, but hide for a year if the customer submits the form - you could edit the form submission event hook like this:\u003C\u002Fp>\u003Cdiv class=\"position-relative w-100 overflow-hidden rounded-2\" data-code-block>\u003Cdiv class=\"d-flex justify-content-end border-bottom\" style=\"background:#2b2c3b;\">\u003Cbutton type=\"button\" class=\"btn btn-link btn-sm text-light\" title=\"Copy\" data-code-button>\u003Cspan data-code-default style=\"\">\u003Ci class=\"fal fa-copy me-2\">\u003C\u002Fi> Copy \u003C\u002Fspan>\u003Cspan class=\"text-success\" data-code-success style=\"display:none;\">\u003Ci class=\"fal fa-check ms-2\">\u003C\u002Fi> Copied \u003C\u002Fspan>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003Cdiv class=\"small\">\u003Cpre class=\"hljs p-2\" data-code-content>$(&#x27;body&#x27;).on(&quot;submit&quot;, &#x27;[data-fc-id=&quot;block-upsell-modal&quot;] form&#x27;, function() { addUpsellCookie(365); });\u003C\u002Fpre>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cp>Finally, you can also comment out either of the event hooks that are triggered on closing the modal or submitting a form, depending on your needs. For example if you only wanted to prevent the upsell from showing again if the customer submits the form, you would comment out this line like this:\u003C\u002Fp>\u003Cdiv class=\"position-relative w-100 overflow-hidden rounded-2\" data-code-block>\u003Cdiv class=\"d-flex justify-content-end border-bottom\" style=\"background:#2b2c3b;\">\u003Cbutton type=\"button\" class=\"btn btn-link btn-sm text-light\" title=\"Copy\" data-code-button>\u003Cspan data-code-default style=\"\">\u003Ci class=\"fal fa-copy me-2\">\u003C\u002Fi> Copy \u003C\u002Fspan>\u003Cspan class=\"text-success\" data-code-success style=\"display:none;\">\u003Ci class=\"fal fa-check ms-2\">\u003C\u002Fi> Copied \u003C\u002Fspan>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003Cdiv class=\"small\">\u003Cpre class=\"hljs p-2\" data-code-content>\u002F\u002F $(&#x27;body&#x27;).on(&quot;mousedown&quot;, &#x27;[data-fc-id=&quot;block-upsell-modal&quot;] [data-remodal-action=&quot;cancel&quot;]&#x27;, function() { addUpsellCookie(); });\u003C\u002Fpre>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fsection>\u003Csection id=\"displaying-a-subscription-cancellation-upsell-or-message\" data-title=\"Displaying a Subscription Cancellation Upsell or Message\" data-title-node=\"H2\">\u003Chr class=\"my-8\" style=\"margin-left: -48px; margin-right: -40vw\">\u003Ch2 data-anchor-id=\"displaying-a-subscription-cancellation-upsell-or-message\">Displaying a Subscription Cancellation Upsell or Message\u003C\u002Fh2>\u003Cp>All the steps above should be followed, but here&#039;s code tailored to display the message based on the \u003Ccode class=\"badge bg-soft-danger text-danger\">is_subscription_cancel\u003C\u002Fcode> value. This will \u003Cem>only\u003C\u002Fem> display when a customer uses a subscription cancellation link:\u003C\u002Fp>\u003Cdiv class=\"position-relative w-100 overflow-hidden rounded-2\" data-code-block>\u003Cdiv class=\"d-flex justify-content-end border-bottom\" style=\"background:#2b2c3b;\">\u003Cbutton type=\"button\" class=\"btn btn-link btn-sm text-light\" title=\"Copy\" data-code-button>\u003Cspan data-code-default style=\"\">\u003Ci class=\"fal fa-copy me-2\">\u003C\u002Fi> Copy \u003C\u002Fspan>\u003Cspan class=\"text-success\" data-code-success style=\"display:none;\">\u003Ci class=\"fal fa-check ms-2\">\u003C\u002Fi> Copied \u003C\u002Fspan>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003Cdiv class=\"small\">\u003Cpre class=\"hljs p-2\" data-code-content>{% block upsell_modal %}\n    {% if is_subscription_cancel %}\n    \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">id\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;cancelConfirmModal&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">h2\u003C\u002Fspan>&gt;\u003C\u002Fspan>Hi there! Before You Cancel...\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">h2\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>We understand things change, but if you&#x27;re cancelling because:\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">ul\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n            \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan>&gt;\u003C\u002Fspan>You&#x27;re not getting the value you expected?\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n            \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan>&gt;\u003C\u002Fspan>Encountering technical difficulties?\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n            \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan>&gt;\u003C\u002Fspan>Finding it complex to use?\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n            \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan>&gt;\u003C\u002Fspan>Have questions about your plan or billing?\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">ul\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>We&#x27;re here to help you get the most out of our service! And we&#x27;re happy to help.\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n            \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">ul\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n            \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n                \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">a\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">href\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;mailto:hello@example.com&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>✉️ Email Support or Schedule a Call\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">a\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n            \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n            \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n                \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">a\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">data-remodal-action\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;cancel&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>No Thanks, Continue to Cancel…\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">a\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n            \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n            \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">ul\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n    {% endif %}\n{% endblock %}\u003C\u002Fpre>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fsection>",[746,749,752,754,756,758],{"id":747,"title":357,"level":748},"step-1-add-custom-twig-to-your-checkout","H2",{"id":750,"title":495,"level":751},"important-notes","H3",{"id":753,"title":516,"level":748},"step-2-enable-upsells",{"id":755,"title":585,"level":748},"step-3-taking-it-further",{"id":757,"title":629,"level":751},"only-showing-the-upsell-window-once-across-customer-sessions",{"id":759,"title":707,"level":748},"displaying-a-subscription-cancellation-upsell-or-message",[761],{"type":762,"content":763},"html","\u003Cp>Beginning in version 2.0 we&#039;ve added some basic upsell functionality into the checkout. It allows you to quickly show a modal window to customers on the checkout providing opportunities for them to add additional products to their cart prior to checkout.\u003C\u002Fp>\u003Cblockquote>\u003Cp>\u003Cstrong>Tip:\u003C\u002Fstrong> It also works on subscription cancellations! If you want to display a message before a customer cancels their subscription, this functionality can handle that as well. (Sample code at the bottom of the page.)\u003C\u002Fp>\u003C\u002Fblockquote>\u003Cp>The upsell modal window is displayed on page load of the checkout, based on conditions you set within your custom Twig logic.\u003C\u002Fp>\u003Ch2>Step 1: Add custom Twig to your checkout\u003C\u002Fh2>\u003Cp>To create the modal window contents, you overwrite a Twig block within your checkout template with your own HTML. When the modal functionality is enabled for your store, the actual modal window will only display to the customer if the block has some HTML elements contained within it. This means that if the block is empty, then it won&#039;t be shown to the customer. This approach is used to allow you to conditionally show the modal to the customer based on your own conditions - such as based on what products are in the cart.\u003C\u002Fp>\u003Cp>In the Foxy admin (\u003Ca href=\"https:\u002F\u002Fadmin.foxy.io\" class=\"\">https:\u002F\u002Fadmin.foxy.io\u003C\u002Fa>), go to \u003Cstrong>Settings &gt; Checkout\u003C\u002Fstrong> and edit the \u003Cstrong>Custom checkout template\u003C\u002Fstrong>:\u003C\u002Fp>\u003Cpre>\u003Ccode>{% embed &#039;checkout.inc.twig&#039; %}\n{% endembed %}\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>It is within these two lines that we&#039;ll be pasting our custom block. If you already have some other code within the \u003Ccode class=\"badge bg-soft-danger text-danger\">embed\u003C\u002Fcode> tags, add this additional block right before the closing \u003Ccode class=\"badge bg-soft-danger text-danger\">{% endembed %}\u003C\u002Fcode> tag. Your own code will be overwriting the \u003Ccode class=\"badge bg-soft-danger text-danger\">upsell_modal\u003C\u002Fcode> block - and as an initial start, will look like this:\u003C\u002Fp>\u003Cpre>\u003Ccode>{% embed &#039;checkout.inc.twig&#039; %}\n{% block upsell_modal %}\n\n{% endblock %}\n{% endembed %}\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>Inside this block tag you&#039;ll place your own custom logic and HTML. The most common use case is that of offering an link or form to add an extra product into the customers cart, unless they already have the product in their cart. That approach could look simply like this:\u003C\u002Fp>\u003Cpre>\u003Ccode>{% block upsell_modal %}\n    {% set showUpsell = true %}\n    {% for item in items %}\n        {% if item.code == &quot;my-upsell&quot; %}\n            {% set showUpsell = false %}\n        {% endif %}\n    {% endfor %}\n    {% if showUpsell %}\n        &lt;h2&gt;Special offer just for you!&lt;\u002Fh2&gt;\n        &lt;p&gt;As a limited time offer, we&#039;re offering you this unique product for only $12.95. That&#039;s $5 off our normal price!&lt;\u002Fp&gt;\n        &lt;p&gt;&lt;a href=&#039;https:\u002F\u002F\u002Fcart?name=Upsell+Product&amp;code=my-upsell&amp;price=12.95&#039;&gt;Yes, please add this product to my cart!&lt;\u002Fa&gt; | &lt;a data-remodal-action=&quot;cancel&quot;&gt;No thanks&lt;\u002Fa&gt;&lt;\u002Fp&gt;\n    {% endif %}\n{% endblock %}\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>A few things happens within this code.\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cp>Firstly, we set a variable called \u003Ccode class=\"badge bg-soft-danger text-danger\">showUpsell\u003C\u002Fcode> to true\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>Next, we loop through the items in the cart and look for any products with a code of \u003Ccode class=\"badge bg-soft-danger text-danger\">my-upsell\u003C\u002Fcode>. If one is present, we set the \u003Ccode class=\"badge bg-soft-danger text-danger\">showUpsell\u003C\u002Fcode> variable to false.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>Finally, if \u003Ccode class=\"badge bg-soft-danger text-danger\">showUpsell\u003C\u002Fcode> is still true, meaning the customer hasn&#039;t previously purchased the upsell - we display some HTML tempting the customer to our upsell product. If they have, and \u003Ccode class=\"badge bg-soft-danger text-danger\">showUpsell\u003C\u002Fcode> is false - we don&#039;t output any HTML, leaving the block empty and so the modal won&#039;t display at all.\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003Ch3>Important Notes\u003C\u002Fh3>\u003Cul>\u003Cli>\u003Cp>If your store has link and form encryption enabled, any add to carts you include within the modal will also need to be encrypted. Review the wiki page for the link\u002Fform encryption for details on doing that.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>Any images that you include within your markup need to be served securely. If you&#039;re not already using a remote custom template that you&#039;re caching, you can have the image cached manually as detailed here.\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>Step 2: Enable Upsells\u003C\u002Fh2>\u003Cp>In the Foxy admin (\u003Ca href=\"https:\u002F\u002Fadmin.foxy.io\" class=\"\">https:\u002F\u002Fadmin.foxy.io\u003C\u002Fa>), go to \u003Cstrong>Settings &gt; Templates\u003C\u002Fstrong> and paste the following into the \u003Cstrong>Custom config\u003C\u002Fstrong> field (valid JSON only):\u003C\u002Fp>\u003Cpre>\u003Ccode>{\n  &quot;upsell&quot;: {\n    &quot;enabled&quot;: true\n  }\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Cblockquote>\u003Cp>\u003Cstrong>Tip:\u003C\u002Fstrong> If you already have some custom JSON set in the custom value text area, you will need to merge this JSON into your own, ensuring that \u003Ccode class=\"badge bg-soft-danger text-danger\">upsell\u003C\u002Fcode> is included within the first level of the JSON object.\u003C\u002Fp>\u003C\u002Fblockquote>\u003Cp>If you set \u003Ccode class=\"badge bg-soft-danger text-danger\">enabled\u003C\u002Fcode> to \u003Ccode class=\"badge bg-soft-danger text-danger\">false\u003C\u002Fcode> in this code - it will disable the upsell functionality from operating on your cart. Alternatively you can also simply remove the above code from the \u003Cstrong>Custom config\u003C\u002Fstrong> field and save your configuration to turn off the upsell functionality.\u003C\u002Fp>\u003Ch2>Step 3: Taking it further\u003C\u002Fh2>\u003Cp>You have complete control over what logic the Twig includes, and what HTML is output within the modal window. As with any Foxy templates, you can also include any custom styles you need - meaning you can create very complex and beautiful upsell displays for your store.\u003C\u002Fp>\u003Cp>Some examples of more advanced set ups you could take:\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cp>Use a custom session attribute to track if a customer has already added or declined an upsell product. This could be done by sending a JSONP request off to the cart on the dismiss link being clicked, and by including the custom attribute in the add to cart. You could then check for that custom attribute in your twig logic to prevent the modal from showing again.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>On page load of the checkout, you could send off a JSONP request setting a custom session attribute of the current date\u002Ftime. You could then check against that variable when deciding whether to show the upsell or not, and include a countdown timer within the modal showing how much longer the offer would be valid for.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>If you wanted to also trigger the upsell modal off of other events on the checkout - such as removing a product from their cart or clicking a button or link - it can be shown by calling \u003Ccode class=\"badge bg-soft-danger text-danger\">FC.checkout.showUpsellModal()\u003C\u002Fcode>. This function will re-render the upsell block and display if it&#039;s enabled and has at least one HTML element within the block to display.\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003Ch3>Only showing the upsell window once across customer sessions\u003C\u002Fh3>\u003Cp>If you want to ensure the customer only sees the upsell modal once across multiple different checkout attempts, you can utilise cookies to store details about the customer that can be retrieved in future checkout sessions. As an example, the following code will add a cookie that will last for 30 days if the customer either closes the upsell modal or submits the add to cart form, preventing the customer from seeing it again for that timeframe.\u003C\u002Fp>\u003Cp>In the Foxy admin (\u003Ca href=\"https:\u002F\u002Fadmin.foxy.io\" class=\"\">https:\u002F\u002Fadmin.foxy.io\u003C\u002Fa>), go to \u003Cstrong>Settings &gt; Templates\u003C\u002Fstrong> and add the code to the \u003Cstrong>Custom footer\u003C\u002Fstrong> field (Twig is supported; it is injected before the closing \u003Ccode class=\"badge bg-soft-danger text-danger\">&lt;\u002Fbody&gt;\u003C\u002Fcode> tag):\u003C\u002Fp>\u003Cpre>\u003Ccode>{% if context == &quot;checkout&quot; %}\n&lt;script&gt;\n    var upsell_cookie_name = &quot;fc_completed_upsell&quot;,\n        cookie_expires_in = 30; \u002F\u002F default, in days\n \n    $(function() {\n        var has_upsell_cookie = document.cookie.split(&#039;;&#039;).filter(function(item) {\n                return item.indexOf(upsell_cookie_name + &#039;=&#039;) &gt;= 0\n            }).length;\n        if (has_upsell_cookie) {\n            $(&#039;[data-fc-id=&quot;block-upsell-modal&quot;]&#039;).html(&quot;&quot;);\n            if (FC.checkout.upsell_modal) {\n                FC.checkout.upsell_modal.close();\n            }\n        }\n \n        \u002F\u002F On closing the modal\n        $(&#039;body&#039;).on(&quot;mousedown&quot;, &#039;[data-fc-id=&quot;block-upsell-modal&quot;] [data-remodal-action=&quot;cancel&quot;]&#039;, function() { addUpsellCookie(); });\n        \u002F\u002F On submitting a form in the modal\n        $(&#039;body&#039;).on(&quot;submit&quot;, &#039;[data-fc-id=&quot;block-upsell-modal&quot;] form&#039;, function() { addUpsellCookie(); });\n    });\n \n    function addUpsellCookie(days) {\n        var expires = &quot;&quot;,\n            date = new Date(),\n            days = parseInt(days);\n        \n        if (typeof days !== &quot;number&quot; || !isFinite(days) || Math.floor(days) !== days) {\n            days = cookie_expires_in;\n        }\n\n        date.setTime(date.getTime() + (days*24*60*60*1000));\n        expires = &quot;; expires=&quot; + date.toUTCString();\n        document.cookie = upsell_cookie_name + &quot;=true&quot; + expires + &quot;; path=\u002F&quot;;\n    }\n&lt;\u002Fscript&gt;\n{% endif %}\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>You can modify this script as needed, updating the \u003Ccode class=\"badge bg-soft-danger text-danger\">cookie_expires_in\u003C\u002Fcode> variable to change the number of days they shouldn&#039;t see the upsell for.\u003C\u002Fp>\u003Cp>The script also supports passing a custom cookie length, in days, to the \u003Ccode class=\"badge bg-soft-danger text-danger\">addUpsellCookie()\u003C\u002Fcode> function, so you could customise the number of days the customer shouldn&#039;t see the upsell modal for depending on what they interact with. If no parameter is passed, then the default value is used from the top of the script (30 days in the example code above). For example, if you wanted to just hide the modal if cancelled for the default amount, but hide for a year if the customer submits the form - you could edit the form submission event hook like this:\u003C\u002Fp>\u003Cpre>\u003Ccode>$(&#039;body&#039;).on(&quot;submit&quot;, &#039;[data-fc-id=&quot;block-upsell-modal&quot;] form&#039;, function() { addUpsellCookie(365); });\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>Finally, you can also comment out either of the event hooks that are triggered on closing the modal or submitting a form, depending on your needs. For example if you only wanted to prevent the upsell from showing again if the customer submits the form, you would comment out this line like this:\u003C\u002Fp>\u003Cpre>\u003Ccode>\u002F\u002F $(&#039;body&#039;).on(&quot;mousedown&quot;, &#039;[data-fc-id=&quot;block-upsell-modal&quot;] [data-remodal-action=&quot;cancel&quot;]&#039;, function() { addUpsellCookie(); });\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch2>Displaying a Subscription Cancellation Upsell or Message\u003C\u002Fh2>\u003Cp>All the steps above should be followed, but here&#039;s code tailored to display the message based on the \u003Ccode class=\"badge bg-soft-danger text-danger\">is_subscription_cancel\u003C\u002Fcode> value. This will \u003Cem>only\u003C\u002Fem> display when a customer uses a subscription cancellation link:\u003C\u002Fp>\u003Cpre>\u003Ccode>{% block upsell_modal %}\n    {% if is_subscription_cancel %}\n    &lt;div id=&quot;cancelConfirmModal&quot;&gt;\n        &lt;h2&gt;Hi there! Before You Cancel...&lt;\u002Fh2&gt;\n        &lt;p&gt;We understand things change, but if you&#039;re cancelling because:&lt;\u002Fp&gt;\n        &lt;ul&gt;\n            &lt;li&gt;You&#039;re not getting the value you expected?&lt;\u002Fli&gt;\n            &lt;li&gt;Encountering technical difficulties?&lt;\u002Fli&gt;\n            &lt;li&gt;Finding it complex to use?&lt;\u002Fli&gt;\n            &lt;li&gt;Have questions about your plan or billing?&lt;\u002Fli&gt;\n        &lt;\u002Ful&gt;\n        &lt;p&gt;We&#039;re here to help you get the most out of our service! And we&#039;re happy to help.&lt;\u002Fp&gt;\n        &lt;div&gt;\n            &lt;ul&gt;\n            &lt;li&gt;\n                &lt;a href=&quot;mailto:hello@example.com&quot;&gt;✉️ Email Support or Schedule a Call&lt;\u002Fa&gt;\n            &lt;\u002Fli&gt;\n            &lt;li&gt;\n                &lt;a data-remodal-action=&quot;cancel&quot;&gt;No Thanks, Continue to Cancel…&lt;\u002Fa&gt;\n            &lt;\u002Fli&gt;\n            &lt;\u002Ful&gt;\n        &lt;\u002Fdiv&gt;\n    &lt;\u002Fdiv&gt;\n    {% endif %}\n{% endblock %}\u003C\u002Fcode>\u003C\u002Fpre>",{"name":765,"created_at":766,"published_at":767,"updated_at":768,"id":769,"uuid":47,"content":770,"slug":48,"full_slug":48,"sort_by_date":59,"position":947,"tag_list":948,"is_startpage":24,"parent_id":59,"meta_data":59,"group_id":949,"first_published_at":950,"release_id":59,"lang":65,"path":59,"alternates":951,"default_full_slug":59,"translated_slugs":59},"Contact","2022-09-23T19:56:58.957Z","2025-05-08T18:24:40.382Z","2025-05-08T18:24:40.392Z",3138,{"seo":771,"_uid":774,"title":775,"action":776,"fields":777,"method":923,"columns":924,"subtitle":938,"component":48,"button_text":944,"submit_title":945,"submit_subtitle":946},{"_uid":772,"title":765,"plugin":773,"description":13},"24ff7574-3bcc-48d2-85b5-e529dfea1cc4","meta-fields","8f54f1da-9d8f-49b2-89e7-840e886491cb","We're here to help.","https:\u002F\u002Fusebasin.com\u002Ff\u002F029f48d65402",[778,783,787,894,897,902,917],{"_uid":779,"name":780,"type":332,"label":781,"options":13,"required":33,"component":782,"placeholder":13},"9a70b226-2036-4f90-a052-b3efa61c5896","name","Name","form___field",{"_uid":784,"name":785,"type":785,"label":786,"options":13,"required":33,"component":782,"placeholder":13},"86ba35be-ff43-4a28-8633-14052a8f6622","email","Email Address",{"_uid":788,"name":789,"type":790,"label":791,"options":792,"required":33,"component":782,"conditions":793,"placeholder":13},"3f827475-492c-4f97-aa1e-2386ac263b6c","topic","select","Topic","Presales, Support, Billing, Partnerships, Order Enquiry, Other",[794,848,858,865,873,881,887],{"_uid":795,"equals":796,"fields":797,"component":847},"e21d97dd-e68e-4fa6-ba97-bc40f3041dde","Order Enquiry",[798],{"_uid":799,"body":800,"type":845,"title":13,"component":846},"b64992bc-6d53-48b8-b7a0-d81e5a062e50",{"type":324,"content":801},[802],{"type":327,"content":803},[804,806,813,815,817,818,822,824,828,836,838,843],{"text":805,"type":332},"We are ",{"text":807,"type":332,"marks":808},"Foxy.io",[809],{"type":372,"attrs":810},{"href":811,"uuid":59,"anchor":59,"custom":812,"target":59,"linktype":31},"http:\u002F\u002FFoxy.io",{},{"text":814,"type":332},", an ecommerce platform powering ecommerce for other merchants. We do not sell products, and are unable to assist with questions about order statuses or refunds for any merchants using our platform. Please contact the merchant you ordered from for assistance. If you’d like to report a store using Foxy for fraudulent practices, please select ‘other’ in the subject.",{"type":816},"hard_break",{"type":816},{"text":819,"type":332,"marks":820},"NOTE:",[821],{"type":343},{"text":823,"type":332}," We are ",{"text":825,"type":332,"marks":826},"not ",[827],{"type":723},{"text":829,"type":332,"marks":830},"Foxy.in",[831,835],{"type":372,"attrs":832},{"href":833,"uuid":59,"anchor":59,"custom":834,"target":59,"linktype":31},"http:\u002F\u002FFoxy.in",{},{"type":723},{"text":837,"type":332},". We are not in any way affiliated with ",{"text":829,"type":332,"marks":839},[840],{"type":372,"attrs":841},{"href":833,"uuid":59,"anchor":59,"custom":842,"target":59,"linktype":31},{},{"text":844,"type":332},", and cannot help in any way with your order from that website.","danger","global___alert","form___condition",{"_uid":849,"equals":850,"fields":851,"component":847},"8765c3e1-25cf-44aa-b8ea-fc6094acf9c3","Presales",[852],{"_uid":853,"name":854,"type":855,"label":13,"options":13,"required":24,"component":782,"conditions":856,"placeholder":13,"default_value":857},"cf464f8e-d643-4f6e-af29-d3abffaf7380","department_email_address","hidden",[],"hello@foxy.io",{"_uid":859,"equals":208,"fields":860,"component":847},"4007b6d8-77e5-421d-bd1e-6f336dd853fb",[861],{"_uid":862,"name":854,"type":855,"label":13,"options":13,"required":24,"component":782,"conditions":863,"placeholder":13,"default_value":864},"7b4c6aa5-a68c-45e0-9ce1-0a36af10c0c2",[],"help@foxy.io",{"_uid":866,"equals":867,"fields":868,"component":847},"1dbb8f11-613d-43cd-9e09-1b94f6e19219","Billing",[869],{"_uid":870,"name":854,"type":855,"label":13,"options":13,"required":24,"component":782,"conditions":871,"placeholder":13,"default_value":872},"a0ac0d1b-bc4f-4a6c-a682-581d450b0b73",[],"help+billing@foxy.io",{"_uid":874,"equals":875,"fields":876,"component":847},"a0a53a50-7172-4a29-ba58-181e38874e12","Partnerships",[877],{"_uid":878,"name":854,"type":855,"label":13,"options":13,"required":24,"component":782,"conditions":879,"placeholder":13,"default_value":880},"7aa011d9-f374-4aed-b5a5-929b54aaf152",[],"partners@foxy.io",{"_uid":882,"equals":796,"fields":883,"component":847},"a4cd431f-25d5-41c7-bfdc-02c908c8fb47",[884],{"_uid":885,"name":854,"type":855,"label":13,"options":13,"required":24,"component":782,"conditions":886,"placeholder":13,"default_value":857},"f5d52168-d6ae-451b-94ee-2ced1cbd28ad",[],{"_uid":888,"equals":889,"fields":890,"component":847},"25aba1ed-eb41-4bbc-aa89-f7a7167ea86e","Other",[891],{"_uid":892,"name":854,"type":855,"label":13,"options":13,"required":24,"component":782,"conditions":893,"placeholder":13,"default_value":857},"f40dfaef-c203-4b71-bf4e-e1b43cef192b",[],{"_uid":895,"component":896},"e9c53a05-f40a-4510-aaf8-bc072a235a0c","form___subject",{"_uid":898,"name":899,"type":900,"label":901,"options":13,"required":33,"component":782,"placeholder":13},"a4c4d385-fff4-4978-99fb-b68cfea623d6","message","textarea","Message",{"_uid":903,"name":904,"type":790,"label":905,"options":906,"required":33,"component":782,"conditions":907,"placeholder":13},"8a3c9f85-f438-427d-9c7a-d7b295a14b5b","existing_user","Are you an existing user?","No, Yes",[908],{"_uid":909,"equals":910,"fields":911,"component":847},"115933d6-262a-4b59-8fa8-579c5ad73de1","Yes",[912],{"_uid":913,"name":914,"type":332,"label":915,"options":13,"required":33,"component":782,"conditions":916,"placeholder":13},"44b6ff23-98f0-4e95-b7f5-c23e06415c2d","subdomain","Store Subdomain",[],{"_uid":918,"name":919,"type":790,"label":920,"options":921,"required":33,"component":782,"conditions":922,"placeholder":13},"922a5cef-3af2-4113-8855-36c7910e3ee3","user_type","What type of user are you?","Developer, Designer, Merchant",[],"POST",[925],{"_uid":926,"text":927,"title":936,"component":937},"7323b90d-a93a-4bf1-baa9-20d0b7ead61b",{"type":324,"content":928},[929],{"type":327,"content":930},[931,933,934],{"text":932,"type":332},"855.369.9227",{"type":816},{"text":935,"type":332},"9:30am-6pm Central M-F","Pre-sales, Sales, & Partnerships","contact___footer_column",{"type":324,"content":939},[940],{"type":327,"content":941},[942],{"text":943,"type":332},"Get in touch to get help from our friendly support team.","Submit","Success!","Your email has been received. We'll get back to you as soon as we can, but it might take a business day. If you don't hear back from us in a timely manner, please check your spam folder to ensure our reply didn't go there.",-80,[],"2fd9fb7d-a48a-4184-acfd-30022d8d6f08","2022-09-23T20:10:45.360Z",[],[288,953,982],{"name":954,"created_at":955,"published_at":956,"updated_at":957,"id":958,"uuid":959,"content":960,"slug":975,"full_slug":976,"sort_by_date":59,"position":977,"tag_list":978,"is_startpage":24,"parent_id":310,"meta_data":59,"group_id":979,"first_published_at":980,"release_id":59,"lang":65,"path":59,"alternates":981,"default_full_slug":59,"translated_slugs":59},"Checkout","2024-11-06T19:56:29.907Z","2026-07-02T22:04:34.438Z","2026-07-02T22:04:34.451Z",14898631,"60b73dc2-7635-487c-bd1f-fd7fba18ab4d",{"_uid":961,"icon":13,"name":954,"type":962,"guides":963,"pinned":24,"summary":964,"category":13,"component":297,"blog_posts":965,"content_hub":24,"icon_custom":966,"case_studies":968,"faq_sections":969,"help_articles":970,"featured_guides":971,"mailbox_category":13,"featured_articles":972,"featured_blog_posts":973,"featured_case_studies":974},"0a484217-201f-4f60-a813-d8d8bda736e4","simple",[],"How the checkout works, configuration options, customizations, and advanced integrations.",[],{"id":59,"alt":59,"name":13,"focus":59,"title":59,"source":59,"filename":13,"copyright":59,"fieldtype":81,"meta_data":967},{},[],[],[],[],[],[],[],"checkout","help\u002Fcategories\u002Fcheckout",0,[],"b3bfcd1f-8386-4ed8-9218-2f4c2989a1b2","2024-11-06T19:56:44.870Z",[],{"name":983,"created_at":984,"published_at":985,"updated_at":986,"id":987,"uuid":734,"content":988,"slug":1000,"full_slug":1001,"sort_by_date":59,"position":1002,"tag_list":1003,"is_startpage":24,"parent_id":310,"meta_data":59,"group_id":1004,"first_published_at":985,"release_id":59,"lang":65,"path":59,"alternates":1005,"default_full_slug":59,"translated_slugs":59},"Customize The Checkout","2026-07-01T21:47:44.740Z","2026-07-01T21:49:01.723Z","2026-07-01T21:49:01.735Z",193547734023485,{"_uid":989,"icon":13,"name":983,"type":962,"pinned":24,"summary":990,"category":959,"component":297,"blog_posts":991,"icon_custom":992,"case_studies":994,"faq_sections":995,"featured_guides":996,"mailbox_category":13,"featured_articles":997,"featured_blog_posts":998,"featured_case_studies":999},"ef453f74-3f14-4304-9824-ab8062d98dc3","Customize the appearance and fields of the checkout.",[],{"id":59,"alt":59,"name":13,"focus":59,"title":59,"source":59,"filename":13,"copyright":59,"fieldtype":81,"meta_data":993},{},[],[],[],[],[],[],"customize-the-checkout","help\u002Fcategories\u002Fcustomize-the-checkout",-500,[],"1d9305ee-1c27-453b-a461-c993ef5b69b5",[],{},1784742856118]