*/ (function() { 'use strict'; const CONFIG = { storageKey: 'aos_utm_data', storageDuration: 30, // days utmParams: ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'], // Shopify attribution mapping shopifyFields: { utm_source: 'source', utm_medium: 'medium', utm_campaign: 'campaign', utm_content: 'content', utm_term: 'term', landing_page: 'landing_site', referrer: 'referring_site' } }; // ============================================ // STEP 1: CAPTURE & STORE UTM PARAMETERS // ============================================ function captureUTMFromURL() { const params = new URLSearchParams(window.location.search); const utmData = {}; let hasUTM = false; CONFIG.utmParams.forEach(param => { if (params.has(param)) { utmData[param] = params.get(param); hasUTM = true; } }); return hasUTM ? utmData : null; } function getStoredUTMData() { try { const stored = localStorage.getItem(CONFIG.storageKey); if (stored) { const data = JSON.parse(stored); // Check if data is still valid (within duration) const timestamp = data.timestamp || 0; const now = Date.now(); const maxAge = CONFIG.storageDuration * 24 * 60 * 60 * 1000; if (now - timestamp < maxAge) { return data; } } } catch (e) { console.error('Error reading UTM data:', e); } return null; } function saveUTMData(utmData) { try { const dataToStore = { ...utmData, timestamp: Date.now(), landing_page: utmData.landing_page || window.location.href, referrer: utmData.referrer || document.referrer || 'direct' }; localStorage.setItem(CONFIG.storageKey, JSON.stringify(dataToStore)); // Also set as cookie for server-side access setCookie(CONFIG.storageKey, JSON.stringify(dataToStore), CONFIG.storageDuration); console.log('UTM data saved:', dataToStore); return dataToStore; } catch (e) { console.error('Error saving UTM data:', e); return null; } } function setCookie(name, value, days) { const date = new Date(); date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); const expires = "expires=" + date.toUTCString(); document.cookie = name + "=" + encodeURIComponent(value) + ";" + expires + ";path=/;SameSite=Lax"; } // ============================================ // STEP 2: MANAGE UTM DATA (NEW OR STORED) // ============================================ function initializeUTMTracking() { // Check for new UTM parameters in current URL const newUTM = captureUTMFromURL(); if (newUTM) { // New UTM found - overwrite stored data console.log('New UTM parameters detected, updating storage'); return saveUTMData({ ...newUTM, landing_page: window.location.href, referrer: document.referrer || 'direct' }); } else { // No new UTM - get stored data const storedUTM = getStoredUTMData(); if (!storedUTM) { // First visit, no UTM - save as direct traffic console.log('First visit without UTM, marking as direct'); return saveUTMData({ utm_source: 'direct', utm_medium: 'none', landing_page: window.location.href, referrer: document.referrer || 'direct' }); } console.log('Using stored UTM data:', storedUTM); return storedUTM; } } // ============================================ // STEP 3: AUTO-APPEND UTM TO INTERNAL LINKS // ============================================ function appendUTMToURL(url, utmData) { try { const urlObj = new URL(url, window.location.origin); // Only add UTM if not already present CONFIG.utmParams.forEach(param => { if (utmData[param] && !urlObj.searchParams.has(param)) { urlObj.searchParams.set(param, utmData[param]); } }); return urlObj.toString(); } catch (e) { return url; // Return original if parsing fails } } function isInternalLink(url) { try { const urlObj = new URL(url, window.location.origin); return urlObj.hostname === window.location.hostname; } catch (e) { // Relative URLs are internal return !url.startsWith('http://') && !url.startsWith('https://'); } } function hasUTMParameters(url) { try { const urlObj = new URL(url, window.location.origin); return CONFIG.utmParams.some(param => urlObj.searchParams.has(param)); } catch (e) { return false; } } function addUTMToInternalLinks(utmData) { if (!utmData) return; // Function to update a single link function updateLink(link) { const href = link.getAttribute('href'); if (!href || href === '#' || href.startsWith('javascript:') || href.startsWith('mailto:') || href.startsWith('tel:')) { return; } // Only update internal links without UTM if (isInternalLink(href) && !hasUTMParameters(href)) { const newHref = appendUTMToURL(href, utmData); link.setAttribute('href', newHref); } } // Update all existing links document.querySelectorAll('a[href]').forEach(updateLink); // Watch for dynamically added links const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { mutation.addedNodes.forEach(node => { if (node.nodeType === 1) { // Element node if (node.tagName === 'A' && node.hasAttribute('href')) { updateLink(node); } // Also check children node.querySelectorAll && node.querySelectorAll('a[href]').forEach(updateLink); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); } // ============================================ // STEP 4: SEND TO SHOPIFY ATTRIBUTION // ============================================ function sendToShopifyAttribution(utmData) { if (!utmData) return; // Method 1: Use Shopify's analytics tracking if (window.ShopifyAnalytics && window.ShopifyAnalytics.lib) { try { const attributionData = {}; Object.keys(CONFIG.shopifyFields).forEach(key => { const shopifyField = CONFIG.shopifyFields[key]; if (utmData[key]) { attributionData[shopifyField] = utmData[key]; } }); // Set landing site if (utmData.landing_page) { attributionData.landing_site = utmData.landing_page; } // Set referring site if (utmData.referrer && utmData.referrer !== 'direct') { attributionData.referring_site = utmData.referrer; } console.log('Sending to Shopify Analytics:', attributionData); // This sets the attribution data for the session if (window.ShopifyAnalytics.lib.config) { window.ShopifyAnalytics.lib.config.Attribution = attributionData; } } catch (e) { console.error('Error setting Shopify attribution:', e); } } // Method 2: Add to checkout attributes (for order-level tracking) addToCheckoutAttributes(utmData); // Method 3: Add to cart note attributes addToCartAttributes(utmData); } function addToCheckoutAttributes(utmData) { // This will be picked up during checkout window._shopifyCheckoutAttributes = window._shopifyCheckoutAttributes || {}; CONFIG.utmParams.forEach(param => { if (utmData[param]) { window._shopifyCheckoutAttributes[param] = utmData[param]; } }); if (utmData.landing_page) { window._shopifyCheckoutAttributes['landing_page'] = utmData.landing_page; } if (utmData.referrer) { window._shopifyCheckoutAttributes['referrer'] = utmData.referrer; } } function addToCartAttributes(utmData) { // Hook into cart form submissions document.addEventListener('submit', function(e) { const form = e.target; // Check if it's a cart form if (form.action && (form.action.includes('/cart/add') || form.action.includes('/cart'))) { // Add hidden fields for UTM data CONFIG.utmParams.forEach(param => { if (utmData[param]) { addHiddenField(form, `attributes[${param}]`, utmData[param]); } }); if (utmData.landing_page) { addHiddenField(form, 'attributes[landing_page]', utmData.landing_page); } if (utmData.referrer) { addHiddenField(form, 'attributes[referrer]', utmData.referrer); } } }); } function addHiddenField(form, name, value) { // Check if field already exists let field = form.querySelector(`input[name="${name}"]`); if (!field) { field = document.createElement('input'); field.type = 'hidden'; field.name = name; form.appendChild(field); } field.value = value; } // ============================================ // STEP 5: AJAX CART HANDLING // ============================================ function interceptAjaxCalls(utmData) { // Intercept fetch calls const originalFetch = window.fetch; window.fetch = function(...args) { let [url, options] = args; if (typeof url === 'string' && url.includes('/cart/add')) { options = options || {}; // Add UTM data to body if it's a POST request if (options.method === 'POST' || !options.method) { try { const body = options.body ? JSON.parse(options.body) : {}; body.attributes = body.attributes || {}; CONFIG.utmParams.forEach(param => { if (utmData[param]) { body.attributes[param] = utmData[param]; } }); if (utmData.landing_page) body.attributes.landing_page = utmData.landing_page; if (utmData.referrer) body.attributes.referrer = utmData.referrer; options.body = JSON.stringify(body); } catch (e) { console.error('Error adding UTM to fetch:', e); } } } return originalFetch.apply(this, [url, options]); }; // Intercept jQuery AJAX if jQuery is loaded if (window.jQuery) { const originalAjax = jQuery.ajax; jQuery.ajax = function(url, options) { if (typeof url === 'object') { options = url; url = options.url; } if (url && url.includes('/cart/add')) { options.data = options.data || {}; if (typeof options.data === 'object') { options.data.attributes = options.data.attributes || {}; CONFIG.utmParams.forEach(param => { if (utmData[param]) { options.data.attributes[param] = utmData[param]; } }); if (utmData.landing_page) options.data.attributes.landing_page = utmData.landing_page; if (utmData.referrer) options.data.attributes.referrer = utmData.referrer; } } return originalAjax.call(this, url, options); }; } } // ============================================ // STEP 6: INITIALIZE EVERYTHING // ============================================ function init() { console.log('Initializing UTM Tracking System...'); // Initialize UTM tracking (capture new or get stored) const utmData = initializeUTMTracking(); if (utmData) { // Add UTM to all internal links if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => addUTMToInternalLinks(utmData)); } else { addUTMToInternalLinks(utmData); } // Send to Shopify attribution sendToShopifyAttribution(utmData); // Intercept AJAX cart calls interceptAjaxCalls(utmData); console.log('UTM Tracking System initialized successfully'); } } // Start the tracking system init(); // Expose utility function to get current UTM data window.getUTMData = function() { return getStoredUTMData(); }; // Expose function to manually clear UTM data window.clearUTMData = function() { localStorage.removeItem(CONFIG.storageKey); console.log('UTM data cleared'); }; })(); Skip to Main Content
Custom Tailoring for the LGBT Community

Custom Tailoring for the LGBT Community

2021 is going to be an exciting year for AOS. One of our biggest projects yet is our women’s collection launch.

Dan: “We’ve always wanted to explore outside of menswear but could never find the resources or indications that it would work.

We’ve served a handful of women here and there, but we’ve kept a low profile because of all the time and energy it requires to fit a man’s drafting pattern to a woman’s body. With our old factory, especially, we wouldn’t have been able to keep up if the numbers were any higher.

Then something unexpected happened.

We ran into a client unlike any other.”

Brown three-piece suit styled with scarf and tie - Articles of Style tailored menswear, womenswear, LGBT suit fashion

Dan never thought, in a million years, that one day he would be dressing a high school “girl.” And I never imagined myself ever wanting to buy a suit, especially at seventeen.

But there’s been radical growth in the complexities of body image and gender identity that has given rise to a new market of consumers.

Dan and I crossed paths in one of the most unlikely ways. And then, something else equally unexpected happened. He contacted me about an old internship inquiry I had sent in a while ago and completely forgot about.

 

Dan: “Traveling from long-time customer to intern to part of the AOS team, Nikki has given us a unique perspective on what AOS can bring to the market. And especially with our new bespoke factory's capacity to make women's suits, we hope to give this industry something truly new and refreshing.”     

Custom formal tartan suit styled with bowtie - Articles of Style bespoke menswear, womenswear, lgbt suit fashion

The biggest problem I’ve seen with womenswear and custom tailoring for women is expanse.

Very few bespoke tailors have an adequate database or client base to serve female customers.

Recent times have seen a few clothing start-ups that create tailored garments specifically for women. While other companies who have successfully created complementary women’s collections remain limited, where women's lines are often much smaller than their primary men’s section. Companies like these also stick to a preferred style and silhouette, which is typically hyper-feminine. There isn’t much room for anything else.

I think the tailoring world concerns itself too much with the binaries of gender roles and stereotypes that are so deeply embedded in its historical legacy. It’s 2021 and the industry is still operating with rules from the 1900s. Things are a lot more rigid than they need to be.

Custom formal tartan suit styled with bowtie - Articles of Style bespoke menswear, womenswear, lgbt suit fashion

The origin story behind tailoring is creating garments unique to the person wearing them. That’s what the word “bespoke” means: to create by the word of the customer—for the customer.

I’d like to see this industry reach back to its roots in a way that exalts universality and diversity as its primary strength—a service that can work between and beyond the lines of gender.

It might not be apparent to everyone, but there’s definitely an LGBT demographic interested in a more inclusive tailoring industry. And it’s not an overnight phenomenon. Generations of drag and minority communities have had to borrow and interpret menswear and are still left wanting high-quality traditional clothing of their own.

Modern men's fashion - black blazer and white trousers tailored by Articles of Style, womenswear, lgbt suit fashion

At AOS, we hope to create a space in the tailoring industry that welcomes women and queer people as equal participants.

One of the best and most innovative features AOS already has to offer is virtual fitting. Customers can be anywhere in the world and still work with us.

Other brands can leave you in the dark, wondering about how the order will turn out. With AOS, you receive a low-stakes try-on garment and can give your own feedback on how it looks and, more importantly, how it feels. You’ll be able to tell our tailors what you like and what you want to have changed before the final garment even begins production.

During this try-on fitting process, we adjust the pattern according to the fitting photos and feedback we receive from customers and give them a chance to discuss the garment beyond fit. 

The beauty of the virtual fitting is that it gives us a unique opportunity to mold our service to each customer. We really get to know the people we work with on an individual basis, and we strive to foster a dialogue where we understand what each person is looking for and tweak their patterns to fit their unique style preferences. 

Black blazer and white trousers styled in streetwear - Articles of Style men's fashion, womenswear, lgbt suit fashion

I’m confident that AOS, as an influential knowledge provider, has the distinct opportunity to welcome LGBT members into the tailoring world in a way that invites them to be a part of a greater network.

In our mission for sustainability, we are also dedicated to a standard of timeless design that is unmatched by any other brand catering to this demographic now. Our garments strike a perfect balance between old and new by merging traditional luxury fabrics with uniquely innovative yet classic garment constructions.

Elegant white dinner jacket with bowtie - formal menswear by Articles of Style, womenswear, lgbt suit fashion

The biggest thing I want people to understand is the dimension and depth this community has in terms of who these people are, how they express themselves, and what they are looking for.

There’s a completely different aspect of reassurance queer people need when they shop that leading industries aren’t attuned to. These people have so much to say in terms of how they want to feel. 

I honestly don’t shop retail very often because I can always expect to find nothing that feels good to wear, and most alteration experiences go sideways. 

It’s exhausting and disheartening feeling excluded in such a simple way, and I’m glad most people don’t know what it’s like. And for those who do know, I have so much compassion.

It’s not as simple as “these trousers are too long" or "this jacket is too baggy.” It has so much more to do with, “does this shirt fall on my body in the right way, in a way that makes me look and feel more like me?”

Custom white suit with tie - elegant men's fashion from Articles of Style., womenswear, lgbt suit fashion
Black modern suit with casual styling - Articles of Style men's tailoring womenswear, lgbt suit fashion

 

I’m hopeful that AOS is at the forefront of making space in the industry for the full spectrum of identities and expressions.

It’s uplifting to know that tailoring can offer clothing that speaks to everyone on an individual basis.

Bespoke is born and exists with each person it serves. It lets you create whatever you want, allowing you to be whoever you want to be.

And at the end of the day, the ability to feel confident in your desire to represent yourself honestly . . . it’s a beautiful thought.

To take a look in the mirror and smile—it’s something everybody deserves.

Thank you, as always, for reading. 

Sincerely yours,

niK

NEED HELP WITH YOUR WARDROBE?


MORE FROM ARTICLES OF STYLE