91³Ô¹ÏÍø

Watch CBS News

In Tribute: Krystle Campbell

BOSTON (CBS) --- She could have been your friend, your sister, your daughter, her smile infectious as pictures show her standing near the field at Fenway Park or on the Boston Common.

Twenty-nine-year-old was just feet from fellow victim when the bombs went off near the Boston Marathon finish line on She was a month away from her 30th birthday.

Krystle never missed a Boston Marathon. She was a Boston girl, after all. She was loud and fun and her energy infectious. She worked hard as a restaurant manager at an Arlington steak restaurant and made friends wherever she went.

The void she has left is evident in the memorials dedicated to her. to Krystle posthumously by University of Massachusetts at Boston and a portrait of the freckled red-head nowMass Bay Community College has also set up a A permanent memorial can be found in Harbor Park.

Campbell was once a catering manager at the , a seasonal cafe on the island. Cafe owner Jeff Dugan said the gazebo was one of Campbell's favorite places to relax.

When she wasn't working, she was . Krystle had a special relationship with her grandmother. Lillian Campbell said her granddaughter called her often and stopped in once a week, for a cup of tea and to talk about life. Krystle had even lived with her grandmother for two years after her grandmother underwent a medical procedure.

Family and friends said she would always speak her mind, that she was beautiful, sometimes a little noisy and everyone loved her for it.

set up to remember Krystle continues to collect photos of her – tailgating at Gillette Stadium while wearing a Tom Brady jersey, goofing off with a friend, posing for a picture – always smiling.

Friend Chris Westphal wrote in the days after the bombing:

"I hope you can see this from heaven. Oh honey they spoke of you at Fenway and they spoke of u in the garden. Your name has crossed the lips of famous leaders. Your face has adorn everywhere in print from newspapers to magazines. you will forever live in infamy. i know with all this attention You would hide those eyes under your sox cap and give that sly grin i knew so well. Those who knew you miss you and we are heartbroken that you are gone. But all the world now knows that you were here! And long after I am gone you will never be forgotten. I miss you so!"

huddled close after the bombings with tears streaming down their face, told a throng of reporters outside their Meford home that it "doesn't make any sense."

It still doesn't.

MORE LOCAL NEWS FROM CBS BOSTON

View CBS News In
CBS News App Open
Chrome Safari Continue
const link = doc.createElement('link'); link.rel = 'stylesheet'; link.href = '/fly/fly/bundles/cbsnewscontent/css/cmp-banner.min.css?v=50747257b890e014813016b79ece0fb2'; doc.head.appendChild(link); doc.body.innerHTML = CONSENT_MESSAGE; } else { el.insertAdjacentHTML('afterend', CONSENT_MESSAGE); } }); } function hidePrivacyMessage() { // Remove from the main document document.querySelectorAll(`.${CONSENT_MESSAGE_CLASS}`).forEach(el => el.remove()); // Remove from inside any iframes document.querySelectorAll('iframe').forEach(iframe => { const doc = iframe.contentDocument || iframe.contentWindow.document; doc.querySelectorAll(`.${CONSENT_MESSAGE_CLASS}`).forEach(el => el.remove()); }); } function activateGatedScripts() { // Handle both new format (cmp-gated-script) and old OneTrust/Ketch format (optanon-category-4) const gatedScripts = Array.from(document.querySelectorAll('script.cmp-gated-script, script.optanon-category-4')); // Activate scripts sequentially with a small delay to avoid timing issues let delay = 0; gatedScripts.forEach(function(placeholder, index) { setTimeout(function() { // Skip if already processed if (placeholder.hasAttribute('data-cmp-processed')) { return; } placeholder.setAttribute('data-cmp-processed', 'true'); const newScript = document.createElement('script'); newScript.type = 'text/javascript'; // Try new format first (data-cmp-src), then fall back to old format (data-src) const src = placeholder.getAttribute('data-cmp-src') || placeholder.getAttribute('data-src'); if (src) { newScript.src = src; } else if (placeholder.textContent) { // Inline script - just copy the content newScript.textContent = placeholder.textContent; } // Handle new format attributes (data-cmp-attrs) - for both inline and external scripts const attrs = placeholder.getAttribute('data-cmp-attrs'); if (attrs) { const tempDiv = document.createElement('div'); tempDiv.innerHTML = '
<\/div>'; const tempAttrs = tempDiv.firstChild.attributes; for (let i = 0; i < tempAttrs.length; i++) { // For external scripts, allow defer/async. For inline scripts, skip them (not valid) if (src || (tempAttrs[i].name !== 'async' && tempAttrs[i].name !== 'defer')) { newScript.setAttribute(tempAttrs[i].name, tempAttrs[i].value); } } } // Copy other attributes from old OneTrust format for (let i = 0; i < placeholder.attributes.length; i++) { const attr = placeholder.attributes[i]; // Skip attributes we've already handled or don't want to copy if (!['class', 'data-src', 'data-type', 'data-cmp-src', 'data-cmp-attrs', 'data-cmp-processed', 'type', 'async', 'defer', 'src'].includes(attr.name)) { newScript.setAttribute(attr.name, attr.value); } } placeholder.parentNode.replaceChild(newScript, placeholder); // If external script, manually trigger window.onload handlers after it loads // This handles widgets that use window.onload for initialization if (src) { newScript.addEventListener('load', function() { // If page already loaded and script set a new onload handler, trigger it if (document.readyState === 'complete' && window.onload) { const originalOnload = window.onload; window.onload = null; // Clear temporarily to prevent loops originalOnload(); // Execute the handler } }); } }, delay); delay += 500; // 500ms delay between each script to allow full loading }); } cbsoptanon.onScriptsReady(function(cmp) { cmp.ot.targetingAllowed(function(allowed) { if (!allowed) { showPrivacyMessage(); } else { activateGatedScripts(); } }); cmp.ot.awaitInitialConsent(function(consent_model) { cmp.ot.addOnConsentChangedHandler(function() { cmp.ot.targetingAllowed(function(allowed) { if (allowed) { hidePrivacyMessage(); activateGatedScripts(); } else { showPrivacyMessage(); } }); }); }); });